2016-02-18 3 views
0

Я пытаюсь создать пользовательскую привязку, чтобы позволить нокауту работать с плагином 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; 
    } 
}; 
+0

Не могли бы вы поделиться своим перепиской? –

ответ

0

Это может помочь: How to clear/remove observable bindings in Knockout.js? Вы можете удалить привязки во всех элементах страницы до того, как она исчезнет из представления ваших данных, а когда появится новая страница, привяжите свою модель просмотра JS к ее элементам.

Для этого вам необходимо отслеживать код JS, элементы которого в настоящее время отображаются, поэтому вы можете привязать их к представлению.

+0

Это может сработать, позвольте мне попробовать! Еще один вопрос заключается в способе нокаута, который позволил бы мне узнать, нужно ли мне делать чистый узел, чтобы избежать его независимо? Существует не так много сценариев, когда мы модифицируем объект, когда он имеет возможность не находиться в dom. Например, возможно, свойство subscriptions что-то, что я могу проверить, чтобы узнать, было ли соединение «сломанным»? –

Смежные вопросы