- Julia Sememova
Создаём чек-лист дел на сайте wix
Отслеживайте свои задачи с помощью списка дел. Вы можете создать чек-лист для себя, своих сотрудников или клиентов.

Описание функционала
В этом примере мы позволяем посетителям сайта отслеживать свои задачи с помощью списка дел. Посетители могут добавлять задачи в список, отмечать задачи как выполненные и удалять выполненные задачи.
Пример кода
to-do
import { getAllTasks, insertTask, updateTask, removeTask } from 'backend/data';
import { local } from 'wix-storage';
const htmlFontFamily = `madefor-display`;
const htmlFontSize = `14px`;
let visitorId;
$w.onReady(function () {
$w('#repeater').data = [];
registerHandlers();
setVisitor();
});
function registerHandlers() {
$w('#repeater').onItemReady(($item, itemData) => {
$item('#taskTitle').text = itemData.title;
if (itemData.isComplete === true) {
$item('#taskCompleteButton').label = 'V';
}
getHTMLtag($item('#taskTitle'), itemData.isComplete);
$item('#taskCompleteButton').onClick(() => changeCompleteStatus($item, itemData));
});
$w('#addButton').onClick(() => createNewTask());
$w('#taskInput').onKeyPress((event) => {
if (event.key === 'Enter') {
createNewTask();
}
});
$w('#clearButton').onClick(() => clearCompletedTasks());
}
function setVisitor() {
visitorId = local.getItem('visitor-id');
if (!visitorId) {
visitorId = Math.random().toString(36);
local.setItem('visitor-id', visitorId);
}
fetchData();
}
async function fetchData() {
$w('#loaderImage').expand();
try {
$w('#repeater').data = await getAllTasks(visitorId);
$w('#loaderImage').collapse();
} catch (error) {
console.error(error);
}
}
async function createNewTask() {
const toInsert = {
title: $w('#taskInput').value,
isComplete: false,
visitorId
};
$w('#taskInput').value = null;
try {
await insertTask(toInsert);
await fetchData();
} catch (error) {
console.error(error);
}
}
async function changeCompleteStatus($item, itemData) {
try {
if ($item('#taskCompleteButton').label === 'V') {
$item('#taskCompleteButton').label = '';
getHTMLtag($item('#taskTitle'), false);
await updateTask(itemData, false);
} else {
$item('#taskCompleteButton').label = 'V';
getHTMLtag($item('#taskTitle'), true);
await updateTask(itemData, true);
}
} catch (error) {
console.error(error);
}
}
// instead of waiting for each remove action to complete, we call the remove function asynchronously and store the promise returned by each
// call in removePromises array. We use Promise.all in order to wait for all calls to complete before returning from the function
async function clearCompletedTasks() {
let removePromises = [];
let remainedTasks = [];
$w('#repeater').forEachItem(async ($item, itemData) => {
if ($item('#taskCompleteButton').label === 'V') {
const removePromise = removeTask(itemData._id);
removePromises.push(removePromise);
} else {
remainedTasks.push(itemData);
}
});
try {
await Promise.all(removePromises);
} catch (error) {
console.error(error);
}
$w('#repeater').data = remainedTasks;
}
function getHTMLtag(taskTitle, del) {
if (del) {
taskTitle.html = `<p style="font-family:${htmlFontFamily}; font-size:${htmlFontSize}"><del>${taskTitle.text}</del></p>`;
} else {
taskTitle.html = `<p style="font-family:${htmlFontFamily}; font-size:${htmlFontSize}">${taskTitle.text}</p>`;
}
}
data.jsw
import wixData from 'wix-data';
export async function getAllTasks(visitorId) {
try {
const results = await wixData.query('MyTasks')
.eq('visitorId', visitorId)
.find();
return results.items;
} catch (error) {
console.error(error);
}
}
export async function insertTask(taskObj) {
try {
await wixData.insert('MyTasks', taskObj);
} catch (error) {
console.error(error);
}
}
export async function updateTask(task, newStatus) {
try {
const toUpdate = {
...task,
isComplete: newStatus
};
await wixData.update('MyTasks', toUpdate);
} catch (error) {
console.error(error);
}
}
// this function is different from the previous ones as it returns a promise
// this is done in order to allow calling it several times without waiting to each call to complete
export function removeTask(taskID) {
try {
const removePromise = wixData.remove('MyTasks', taskID);
return removePromise;
} catch (error) {
console.error(error);
}
}
Как создать аналогичный функционал
Мы создали коллекцию MyTasks со следующими полями:
Заголовок: название задачи
isComplete: указывает, завершена ли задача

Для простоты работы, на данный момент любой пользователь может изменять данные коллекции, но при использовании этого примера на вашем сайте всегда предпочтительнее предоставлять только необходимые разрешения для доступа к вашей коллекции.
Элементы страницы
На нашей главной индексной странице мы добавили следующие элементы:
TextInput: для ввода текста для новой задачи.
Кнопка: для добавления новой задачи в список.
Repeater: для отображения текущих задач. Каждый элемент содержит текстовый элемент, содержащий название задачи, и кнопку для отметки задачи как выполненной.
Кнопка: для удаления всех выполненных задач из списка.
Серверный код
Мы обрабатываем все операции, связанные с коллекцией, в веб-модуле data.jsw. Веб-модуль включает в себя функции для получения всех текущих задач, вставки новой задачи, обновления задачи и удаления задачи. Мы рекомендуем использовать внутренний код при доступе к коллекции из соображений безопасности.
Код на странице
Мы зарегистрировали следующие обработчики событий:
onItemReady: запускается для каждой задачи, показанной в повторителе. Для каждой задачи нам нужно показать ее как выполненную или незавершенную, в соответствии с ее статусом, и зарегистрировать соответствующий переключатель в обработчике события changeCompletedStatus.
createNewTask: выполняется либо при нажатии кнопки «Добавить», либо при нажатии клавиши «Ввод», когда фокус находится на элементе TextInput.
clearCompletedTasks: запускается при нажатии кнопки Clear Completed.
Мы вызываем fetchData(), которая заполняет повторитель задачами, хранящимися в коллекции. Во время выполнения операции отображается gif-файл загрузчика.