Я пытаюсь создать пользовательскую привязку, чтобы позволить нокауту работать с плагином jQuery datatables, и у меня есть интересная проблема. Само связывание - это не проблема, проблема возникает из-за того, как работает datatable.нокаут 3.4 - Обнаружение прерывания подписки и исправление
- DataTables 1.10
- Нокаут 3,4
Вот сценарий:
данных и элементы все связаны друг с другом посредством связывания пользовательского нокаута. Все работает как ожидалось, за исключением случаев, когда объект модели наблюдаемого вида модифицирован, но элемент html, к которому привязан объект, в настоящее время не находится на странице. Как это произошло? Ну, когда у вас есть данные, настроенные для пейджинга, и у вас больше элементов, чем на одной странице, то в datatable помещаются только те элементы, которые существуют на этой странице данных в DOM. Когда вы перемещаете страницы, он сворачивает элементы html.
Так что, если вы изменяете наблюдаемый объект и этот объект привязан к элементам html на другой странице объекта datatables, то происходит, что привязка объекта к элементу html больше не работает. Он работает, если вы измените элемент html, когда он находится в поле зрения. Значение передается объекту. Однако, как только вы изменяете объект, а элемент html не находится в поле зрения, вы больше не можете изменять объект и нажимать значение на элемент html.
Я считаю, что это происходит потому, что, когда наблюдаемый объект переходит к значению в элемент html, а его нет, он не может повторно подписаться на элемент html, чтобы он больше не мог отправлять уведомления.
Что я хочу сделать, это поместить обратный вызов draw в элемент управления DataTables, который смотрит на элемент данных и html и определяет, была ли эта подписка нарушена или нет. Это позволит мне исправить сломанную подписку, поскольку строки выгружаются, когда пользователь пейджинговый. Можно ли определить, нарушена ли подписка и «исправить ее», используя API нокаута.
Мой вопрос действительно о нокауте не о плагине jquery datatables и о том, что я пытаюсь сделать. Я просто подумал, что необходимо предоставить контекст, почему элемент может отсутствовать в определенный момент, когда наблюдаемый будет обновляться.
Любая помощь будет оценена!
Update Используя ответ ниже я решить мою проблему, но не так эффективно, как хотелось бы надеяться, потому что я до сих пор не имеют возможности обнаружить если подписка сломана. На данный момент я просто удалить привязок и повторно их, когда DataTable страницы, как так:
rowCallback: function (row, data, index) {
var koContext = ko.contextFor(row);
ko.cleanNode(row);
ko.applyBindings(koContext, row);
}
** Update 2 ** Для всех, кто может столкнуться с этим здесь полное связывание я создал
/*
* Knockout Binding that allows for the developer to generate content in a datatable
* that is bound to view model objects via knockout. Based on: https://github.com/zachpainter77/DatatablesForEach-Custom-Knockout-Binding
*/
ko.bindingHandlers.dtForeach = {
page: 0,
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var options = ko.unwrap(valueAccessor());
var nodes = Array.prototype.slice.call(element.childNodes, 0);
ko.utils.arrayForEach(nodes, function (node) {
if (node && node.nodeType !== 1) {
node.parentNode.removeChild(node);
}
});
return ko.bindingHandlers.foreach.init(element, options.data, allBindings, viewModel, bindingContext);
},
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var options = ko.unwrap(valueAccessor()), key = 'DataTablesForEach_Initialized';
var dtData = ko.unwrap(options.data);
var dtOptions = ko.unwrap(options.dataTableOptions);
var tableElement = $(element).closest('table');
/*
* Destroy old table and reinitialize it with
* new data
*/
var table = tableElement.DataTable();
if (dtOptions !== undefined && dtOptions.paging) {
ko.bindingHandlers.dtForeach.page = table.page();
}
table.destroy();
ko.bindingHandlers.foreach.update(element, options.data, allBindings, viewModel, bindingContext);
var bdtOptions = ko.bindingHandlers.dtForeach.setupOptions(dtOptions);
table = tableElement.DataTable(bdtOptions);
if (bdtOptions.paging) {
if (table.page.info().pages - ko.bindingHandlers.dtForeach.page == 0)
table.page(--ko.bindingHandlers.dtForeach.page).draw(false);
else
table.page(ko.bindingHandlers.dtForeach.page).draw(false);
}
if (!ko.utils.domData.get(element, key) && (options.data || options.length))
ko.utils.domData.set(element, key, true);
return { controlsDescendantBindings: true };
},
setupOptions: function (options) {
/*
* Make a deep copy of options because DataTables code
* sometimes changes settings and we want to make some modifications for
* this binding
*/
var bdtOptions = {};
if (options !== undefined)
$.extend(true, bdtOptions, options);
/*
* Need to register a row callback so that bindings are maintained
* for rows that are not visible when paging
*/
if (bdtOptions.paging) {
bdtOptions.rowCallback = function (row, data, index) {
var koContext = ko.contextFor(row);
ko.cleanNode(row);
ko.applyBindings(koContext, row);
}
}
return bdtOptions;
}
};
Не могли бы вы поделиться своим перепиской? –