Я — начинающий front-end разработчик. Сейчас я учусь и стажируюсь в одной минской IT компании. Изучение основ web-ui проходит на примере JS библиотеки Webix и я хочу поделиться своим скромным опытом и сохранить его в виде небольшого учебного пособия по этой интересной UI библиотеке.
ЧЕТВЕРТАЯ ЗАДАЧА
В работе с данными важно иметь возможность выполнить несколько типов операций. В web разработке за это отвечает CRUD — четыре базовые функции. У библиотеки Webix есть все средства для реализации CRUD. Основой для решения новых задач мне послужит материал из предыдущих публикаций: создание интерфейса приложения, модулей проекта и работа с формами. В этой статье будут рассмотрены следующие задачи:
- редактирование данных таблицы через форму;
- установка встроенного редактора строк;
- добавление данных в список и диаграмму;
- удаление элементов;
В документации можно ознакомиться с использованными в статье виджетами List, Treetable, Table.
Исходники находятся по ссылке.
С получившимся демо приложения можно ознакомиться тут.
Шаг 1. Редактирование данных через форму
В этом шаге я буду работать со вкладкой «Dashboard» в которой отрисованы таблица и форма. Код таблицы находится в файле table.js, код формы в form.js.
В статье “Работа с формами” новые записи добавлялись методом add(), который был дополнен валидацией формы. Теперь форма будет использована и для редактирования записей.
Виджету Table я добавлю событие onAfterSelect.
При срабатывании этого события я получу данные из таблицы и передам их в поля формы.
const table = {
view:"datatable",
id:"film_list",
scroll:"y",
select:true,
url:"data/data.js",
hover:"myhover",
columns:[
{ id:"rank", header:"", width:50, css:"rank"},
{ id:"title", header:"Film title", fillspace:true},
{ id:"year", header:"Released", width:100},
{ id:"votes", header:"Votes", width:100},
{ id:"rating", header:"Rating", width:100}
],
on:{
onAfterSelect(id){
let values = $$("film_list").getItem(id);
$$("film_form").setValues(values)
}
}
}
Метод setValues(), в приведенном коде, отвечает за передачу полученных значений в форму.
Запускаю код и проверяю результат:
Как только строка в таблице выбрана, её данные автоматически попадают в форму и готовы к работе.
Теперь я усложняю процесс: новая запись, как и прежде, будет добавляться в таблицу; если же данные взяты из таблицы и отредактированы, то сохраняю эти изменения.
Перепишу функцию saveItem и добавлю в нее новые методы:
let saveItem = () => {
let form = $$( "film_form" );
let list = $$( "film_list" );
let item_data = $$("film_form").getValues();
if( form.isDirty() && form.validate() ){
if( item_data.id )
list.updateItem(item_data.id, item_data);
else
list.add( item_data );
}
}
Теперь у функции следующий алгоритм:
- в начале запускается проверка двух условий — прошли ли данные формы валидацию, и произошли ли в форме изменения. Изменения в форме отслеживает метод isDirty();
- после этого, условие «item_data.id» позволяет определить новую запись. В форму передается строка со всеми ее данными, включая id, для которого в форме нет текстового поля, зато для данных он обязателен. Форма хранит и позволяет считывать все переданные значения, поэтому используем id для проверки;
- после сверки записей происходит либо добавление новой записи — методом add(), либо обновление текущего элемента новыми свойствами.
Для обновления отредактированных данных используется метод updateItem(). Метод принимает два параметра: id выбранного элемента и набор новых свойств взятых из формы. При вызове функции текущие данные заменяются и дополняются новыми.
Результат:
Шаг 2. Установка встроенного редактора
В предыдущем шаге я рассмотрел вариант редактирования данных таблицы при помощи формы. Но форма на странице нужна не всегда, поэтому я реализую способ редактирования прямо в элементе. Этот способ применим как в таблице, так и в других компонентах для работы с большим количеством данных — например в списке.
Начну с древовидной таблицы во вкладке “Products”. Код таблицы находится в файле products_module.js.
Виджет Treetable позволяет редактировать содержимое таблиц, но по умолчанию эта функция отключена. Редактирование настраивается в двух местах: в конфигурации таблицы, настройкой
editable:true
, и в конфигурации каждой колонки. Колонкам устанавливается настройка editor:”text”
. Атрибут “text” задает тип редактора. Подробнее о типах редактора описано в документации.const products = {
editable:true,
view:"treetable",
scrollX:false,
columns:[
{ id:"id", header:"", width:50 },
{ id:"title", header:"Title", fillspace:true,
template:"{common.treetable()} #title#", editor:"text" },
{ id:"price", header:"Price", width:200, editor:"text" }
],
select:"row",
url:"data/products.js",
rules:{
"price":webix.rules.isNotEmpty,
"title":webix.rules.isNotEmpty
}
}
В коде я добавил редакторы для колонок Title и Price. По клику на любую ячейку в них откроется редактор — текстовое поле:
Теперь перейду во вкладку “Users”, и разберу вариант с редактированием виджета List. Код виджета находится в файле users_module.js.
Редактирование данных доступно по умолчанию для виджетов TreeTable и DataTable.Чтобы использовать встроенный редактор в других виджетах, можно задействовать специальный модуль EditAbility. Этот модуль я использую, чтобы редактировать данные виджета List. Для этого, я на основе виджета LIst я создам пользовательский компонент при помощи метода protoUI.
Записываю имя — свойство name — будущего виджета и наследую для виджет-основы нужные модули.
Прототип виджета List:
webix.protoUI({
name:"editlist"
}, webix.EditAbility, webix.ui.list);
После вызова protoUI получаю готовый компонент. В виджет он встраивается так же, как и все остальные — настройкой
view:"editlist"
.view: "editlist",
editable:true,
editor:"text",
editValue:"name",
id:"user_list",
select:true,
url:"data/users.js",
template:"#name# from #country# <span class='webix_icon wxi-close'></span> "
}
Поскольку в каждой записи может быть много полей, а в template листа отрисовано сразу name и country, в конфигурации добавлена настройка —
editorValue:”name”
, указывающее на то, какое поле можно отредактировать. Результат:
Шаг 3. Добавление данных в список и диаграмму
В этой части статьи использованы виджеты List и Chart., код которых расположен в файле users_module.js, и отрисован во вкладке "Users".
Виджеты Chart и List используют одни и те же данные — массив JSON. Поэтому когда я реализую возможность добавления данных, нужно чтобы они попадали в оба компонента.
Для этого в модуле users я отрисую кнопку «Add new person».
{
cols:[
{
view:"button",
id:"btn_add_person",
value:"Add new person",
width:150, css:"webix_primary",
click:addPerson
},
{}
]
}
Клик по кнопке, вызывает функцию addPerson добавляющую в список новую запись.
В диаграмме отображается возраст из каждой записи, поэтому для большего разброса будет генерироваться рандомное число.
Функция добавления новой записи:
let addPerson = () => {
let obj = {
name:"Some name",
age:Math.floor(Math.random() * 80) + 10,
country:"Some country"
}
$$("user_list").add(obj);
$$("chart").add(obj);
};
Результат:
Шаг 4. Удаление элементов
Удаление элементов будет продемонстрировано на примере виджета List — вкладка Users и виджета Table — вкладка "Dashboard".
Для начала, в виджете Table я создам новую колонку в которую помещу html-тег с иконкой.
Чтобы отследить клики по иконкам, нужно использовать свойство таблицы onClick. Это объект, который хранит обработчики, связанные с элементами по одному из их CSS классов — у меня, это
"delete_icon"
.Для обработки кликов по иконкам, беру их класс delete_icon и записываю его в объект onClick как ключ, значение этого ключа будет функция — наш обработчик. Среди аргументов приходит id записи, так что ничто не мешает её удалить методом remove().
Код виджета Table:
const table = {
view:"datatable",
id:"film_list",
scroll:"y",
select:true,
url:"data/data.js",
hover:"myhover",
columns:[
{ id:"rank", header:"", width:50, css:"rank"},
{ id:"title", header:"Film title", fillspace:true},
{ id:"year", header:"Released", width:100},
{ id:"votes", header:"Votes", width:100},
{ id:"rating", header:"Rating", width:100},
{ header:"", template:"<span class='webix_icon wxi-close delete_icon'></span>",
width:35}
],
onClick:{
delete_icon(e, id){
this.remove(id);
return false;
}
},
on:{
onAfterSelect(id){
let values = $$("film_list").getItem(id);
$$("film_form").setValues(values)
}
}
}
Алгоритм удаления строки у виджета List, такой же как и у виджета Table:
{
view: "editlist",
editable:true,
editor:"text",
editValue:"name",
id:"user_list",
select:true,
url:"data/users.js",
template:`#name# from #country#
<span class='webix_icon wxi-close delete_icon'></span> `,
onClick:{
delete_icon(e, id){
this.remove(id);
return false;
}
}
},
Результат удаления строк во вкладке Users:
С готовым приложением можно ознакомиться тут.
Заключение
Реализация CRUD при помощи js библиотеки Webix достигается различными способами: Для изменения данных есть встроенные редакторы, и API, которое позволяет делать то же самое, но уже через стороннюю форму. Добавление данные имеет различные сценарии, а в форме можно осуществить весь набор функций CRUD. Методы реализуются при помощи нескольких строк кода. Архитектура библиотеки позволяет легко комбинировать между собой различные функции.
EvgeniiR
Дополню — CRUD не единственный способ дела делать — cqrs.wordpress.com/documents/task-based-ui.