Webix DataProcessor - это миксин, который позволяет "общаться" с сервером. Основной функционал DataProcessor:
Если не использовать DataProcessor, то для подготовки данных к дальнейшему использованию вам необходимо будет добавить соответствующие функции в события компонента (onAfterInsert/Update/Delete).
Чтобы посмотреть полный список методов, свойств и событий DataProcessor, перейдите в раздел API.
Вы можете инициализировать DataProcessor в момент инициализации компонента или любое другое время.
DataProcessor автоматически инициализируется, когда вы определяете свойство save у компонента-мастера, как путь к скрипту для сохранения данных:
webix.ui({
view:"datatable",
autoConfig:true,
url:"data_load.php", // ваш скрипт для загрузки
save:"data_save.php" // ваш скрипт для сохранения
});
Related sample: Server-side Integration: List
Если для загрузки и сохранения данных используется один и тот же скрипт, укажите свойству save значение true:
webix.ui({
view:"datatable",
autoConfig:true,
url:"data_load.php", // ваш скрипт для загрузки данных
save:true // ваш скрипт для сохранения данных
});
DataProcessor можно инициализировать отдельно от компонента. Это можно сделать с помощью хелпера dp или конструктора DataProcessor.
const dp1 = webix.dp({
id:"listDP", // опционально. ID генерируется автоматически
master:$$("mylist"),
url:"some_script.php",
// другие свойства
});
const dp2 = new webix.DataProcessor({
id:"listDP", // опционально. ID генерируется автоматически
url:"data.php",
master:$$("mylist"),
// другие свойства
});
И dp, и конструктор требуют объект с как минимум двумя полями в качестве параметра:
Смотрите весь список параметров.
DataProcessor отслеживает операции на стороне клиента и отправляет POST запрос к серверному скрипту, который указан в свойстве save. Вместе с запросом DataProcessor отправляет название и тип операции:
Помимо названия операции, запрос содержит данные об изменённой/добавленной/удалённой записи.
Form Data запроса
id 7
title The Shawshank Redemption
webix_operation delete
С помощью параметра operationName вы можете указать другое имя для операции.
Webix DataProcessor также умеет работать с RESTful запросами через прокси. В этом случае методы и операции следующие:
Чтобы активировать rest прокси, добавьте "rest->" перед путём к вашему срипту:
view: "datatable",
save: "rest->/samples/server/films",
В режиме REST Webix не включает "webix_operation" в запрос, т.к. тип операции определяется типом запроса.
Related sample: Datatable: Data Saving with NodeJS
Вы можете написать свою логику для операций сохранения. В этом случае данные сохраняются автоматически, а также появляется возможность модифицировать запросы на сервер. Кастомизация логики сохранения возможна с помощью определения свойства save как:
1. 'save' как функция. В этом случае название операции не включено в отправляемые данные, однако передаётся в функцию параметром. Ниже представлены все параметры функции:
webix.ui({
view:"datatable",
save:function(id, operation, update){
if (operation === "insert")
return webix.ajax().post(
"/server/films",
update
);
/* ...другие операции */
}
});
// или для dataprocessor, инициализированного отдельно
const dp = new webix.DataProcessor({
master:"datatable1",
url: function(id, operation, update){
if (operation === "insert")
return webix.ajax().post(
"/server/films",
update
);
/* ...другие операции */
}
});
2. Вы можете описать логику сохранения отдельно для каждого типа операции. Для этого определите 'save' как объект. Каждое свойство может быть или путём к скрипту, или функцией:
webix.ui({
view:"datatable",
save:{
// функции или строки с URL
insert: function(id, operation, update){
return webix.ajax().post(
"/server/films",
update
);
},
update: function(id, operation, update){ /* ... */ },
delete: function(id, operation, update){ /* ... */ }
}
});
3. Вы также можете указать прокси для сохранения данных. В этом случае вам также необходимо определить save как функцию. Функция принимает следующие параметры:
В случае прокси для сохранения данных, название операции доступно в объекте изменения:
Прокси для сохранения
view:"datatable",
save:{
$proxy:true,
save:function(view, update, dp){
var id = update.data.id;
if (update.operation == "insert")
return webix.ajax().post("/samples/server/films", update.data);
// ... другие операции
}
}
Или для DataProcessor, инициализированного отдельно:
new webix DataProcessor({
master:"datatable1",
url: {
$proxy:true,
save:function(view, update, dp){ /* ... */ }
}
});
Related sample: Datatable: Saving Data with Proxy and Url
У DataProcessor есть набор методов и свойств для изменения шаблона обработки данных по умолчанию.
Если вы хотите использовать API DataProcessor при инициализации, вам необходимо определить свойство save как объект с путями/функциями для сохранения в свойстве url и других. Конфигурация DataProcessor выглядит следущим образом:
webix.ui({
view:"datatable",
save:{
url: "some/path", // или функция, объект, прокси
on:{
onAfterSave(){ /* */ }
},
operationName: "operation",
/* ...другие свойства конфигурации */
}
});
Чтобы использовать API динамически, вы можете получить DataProcessor через метод dp, передав в него ID компонента-мастера:
const dp = webix.dp($$("mylist")); // возвращаем объект dataprocessor для компонента "list"
Или же передав в метод ID DataProcessor (если вы указывали его при инициализации):
const dp = webix.dp($$("mydp"));
В случае успешного сохранения данных сервер должен вернуть данные со следующими параметрами:
Параметр ID является обязательным только для новых записей. Запись добавляется в UI компонент, где получает временное ID. На сервере же у этой записи другое ID, предоставляемое базой данных.
Если вы вернёте этот серверный ID как параметр ответа, DataProcessor автоматически заменит клиентский ID на серверный. Обратите внимание, что поле id можно возвращать только как новый ID, или же как id и newid для старого и нового ID соответственно.
В случае ошибки при сохранении данных, ответ с сервера должен содержать следующее:
Обратите внимание, что пустой ответ расценивается как ошибка и вызовет соответствующие события с полем status:"error".
Обработка событий описана ниже.
Как было заявлено ранее, new ID автоматически замещает временное клиентское ID. Это поведение DataProcessor по умолчанию, поэтому дополнительных действий не требуется.
Кроме этого, вы можете обновлять данные всех полей, которые участвуют в операциях insert и update. Что нужно добавить в код:
При явной инициализации DataProcessor
new webix.DataProcessor({
updateFromResponse:true,
master:"datatable1",
url:"..."
});
При неявной инициализации DataProcessor
view:"datatable",
save:{
url:"...",
updateFromResponse:true
}
Related sample: Datatable: Updating
Это может быть полезно в случае REST-full приложений или же когда вам необходимо заполнить клиентские поля, значения которых можно получить только с сервера.
События DataProcessor позволяют отслеживать изменения данных на клиенте. Что можно делать:
1) Изменять данные перед отправкой на сервер с помощью события onBeforeDataSend, которое принимает весь объект данных в качестве параметра:
dp.attachEvent('onBeforeDataSend', function(obj){
obj.data.StartDate = webix.i18n.dateFormatStr(obj.data.StartDate);
});
Или добавлять обработчики для конкретных операций, например с помощью события onBeforeDelete:
webix.dp($$("grid")).attachEvent("onBeforeDelete", function(id, action){
action.operation = "update";
action.data.deleted = webix.i18n.parseFormatStr(new Date());
});
2) Отслеживать ответы в случае успеха с помощью метода onAfterSync:
Успешный ответ с сервера
dp.attachEvent('onAfterSync', function(statusObj, text, data, loader){
//statusObj {status:"success", id:"12"}
var hash = data.json().data;
//hash { id:"12"}
});
Посмотрите на данные ответа, чтобы получить более детальную информацию.
3) Отслеживать ответы в случае ошибки с помощью события onAfterSaveError:
Ответ в случае ошибки
dp.attachEvent('onAfterSaveError', function(id, status, response, details){
// id - record id
// status - response status {id:"1", status:"error"}
});
В случае ошибки при сохранении, ответ с сервера должен содержать статус "error" или "invalid".
Вы можете отследить момент, когда данные сохраняются на сервер с помощью метода waitSave. waitSave ожидает функцию с одной или несколькими операциями и возвращает промис, который выполняется в случае успешного сохранения данных или не выполняется в случае ошибки.
Например, вот так вы можете добавить данные в компонент и отследить результат. Если операция одна, промис возвращает объект, который пришёл с сервера:
$$("grid").waitSave(function(){
this.add({
rank:99, title:"", year:"2012", votes:"100"
});
}).then(function(obj){
// сервер возвращает объект данных с серверным ID
$$("grid").select(obj.id);
});
Если же вы хотите отследить результат нескольких операций сохранения, промис вернёт массив объектов:
$$("grid").waitSave(function(){
for (var i = 0; i < 3; i++){
this.add({
rank:99, title:"", year:"2012", votes:"100"
});
}
}).then(function(arr){
for (var i = 0; i < arr.length; i++){
$$("grid").select(arr[i].id, i);
}
});
Related sample: Datatable: Wait Saving
Если вы не желаете сразу сохранять все изменения на сервер, вы можете временно отключить DataProcessor. Существует несколько способов:
webix.dp($$("grid")).ignore(function(){
$$("grid").add(data);
});
dp.off();
$$("grid").add(data);
dp.on();
// изначально при инициализации dp
new webix.DataProcessor({
master:"datatable1",
url:"...",
autoupdate:false
});
// динамически
webix.dp($$("datatable1")).define("autoupdate", false);
Чтобы отправить конкретные изменённые данные, используйте метод save с ID элемента и названием операции в качестве параметров:
webix.dp($$("datatable1")).save(1, "update");
Вы также можете сохранить все изменения сразу - читайте подробнее здесь.
Вы можете отслеживать Д-н-Д операции и перемещение элементов, а также другие CRUD операции при активном свойстве trackMove.
new webix.DataProcessor({
master: tree,
url: "...",
trackMove:true
});
Related sample: Server-side Integration: Tree
Валидировать данные можно с помощью специальных правил для полей ввода. Более подробную информацию читайте здесь. Правила позволяют валидировать данные каждый раз, когда вы пытаетесь сохранить их в базу данных.
dp = new webix.DataProcessor({
rules:{
$all:webix.rules.isNotEmpty
},
url: "save.php",
master: $$("mylist")
});
По умолчанию вы не можете отправлять заголовки в запросах DataProcessor, т.к. они выполняются в фоновом режиме. Однако есть несколько вариантов, как это можно сделать:
1. Если DataProcessor отправляет запросы самостоятельно, вы можете отслеживать событие onBeforeAjax, чтобы изменять любой AJAX-запрос со страницы:
webix.attachEvent("onBeforeAjax",
function(mode, url, data, request, headers, files, promise){
headers["Content-type"] = "application/json";
}
);
2. Если же вы используете функцию save или прокси для сохранения, вы можете добавить заголовки с помощью метода webix.ajax().header().
Related sample: Saving: Proxy and Url
По умолчанию все изменения данных сначала применяются на клиенте и только после этого отправляются на сервер. Вы можете отправить данные на сервер в любой момент с помощью метода save. Метод ожидает следующие параметры:
save() возвращает промис с объектом ответа сервера. Промис можно использовать при обновлении клиентских данных. Обратите внимание, чтобы избежать ещё одного ненужного сохранения данных, вам необходимо обернуть клиентскую операцию в ignore.
webix.dp($$("list")).save(
webix.uid(),
"insert",
{ name:"New User", email:"", roles:"" }
).then(function(obj){
webix.dp($$("list")).ignore(function(){
$$("list").add(obj);
});
});
Чтобы отследить неудачное сохранение данных, добавьте ещё один обработчик в then():
webix.dp($$("list")).save(
webix.uid(),
"insert",
{ name:"New User", email:"", roles:"" }
).then(function(obj){
webix.dp($$("list")).ignore(function(){
$$("list").add(obj);
});
}, function(){
webix.message("Data were not saved");
});
Related sample: Datatable: Pessimistic Data Saving
Вы можете инициализировать DataProcessor без компонента-мастера:
var serverData = new webix.DataProcessor({ url:"/server/patients" });
Преимущества такого подхода:
Код "пессимистичного" сохранения данных в этом случае будет короче:
serverData.save(
webix.uid(),
"insert",
{ name:"New User", email:"", roles:"" }
).then(function(obj){
$$("list").add(obj);
});
Related sample: Datatable: Pessimistic Data Saving