Обновление модели нокаута при использовании предварительной привязки к массиву объектов

#knockout.js

#knockout.js

Вопрос:

Я следую примеру здесь, чтобы создать пользовательскую привязку. Свойство, подлежащее обновлению, получается следующим образом в документации:

         var value = valueAccessor();
        value(false);
  

В моем коде таблица привязывается к массиву объектов с помощью foreach привязки нокаута.

  <tbody data-bind="foreach: {data: sites, as: 'site'}">
    <td class="siteid" data-bind="text: site.siteid"></td>
    <td class="expirydate" data-bind="datepicker: site.expirydate"></td>
          et cetera
  

Таблица, похоже, правильно заполнена данными. Все значения находятся в нужном месте.

Объекты в массиве имеют несколько строковых свойств и пару дат, поэтому к нескольким ячейкам таблицы прикреплены указатели даты пользовательского интерфейса jQuery. Вот пользовательский код привязки datepicker, который я использую, который я нашел здесь, на SO, хотя у меня нет под рукой ссылки (насколько я помню, это было из ответа мистера Нимейера).

 ko.bindingHandlers.datepicker = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            //initialize datepicker with some optional options
            var options = allBindingsAccessor().datepickerOptions || {},
                $el = $(element);

            $el.datepicker(options);

            //handle the field changing
            ko.utils.registerEventHandler(element, "change", function () {
                var observable = valueAccessor();
                var newVal = $el.datepicker("getDate")
                observable(newVal);
               // a breakpoint is set at this location
            });
          .
          .
          . <snip>
  

Код вылетает при observable(newVal);

Однако, если я изменю

 var observable = valueAccessor(); 
  

Для

  var observable = valueAccessor;
  

затем код выполняется без ошибок. Но когда я проверяю значение в observable впоследствии, в месте точки останова, оно не содержит значения даты в newVal ; скорее, оно содержит исходное значение даты.

И если вместо observable(newVal) я попробую это вместо:

      allBindingsAccessor().value(newVal);
  

Я получаю сообщение об ошибке: «Объект не поддерживает свойство или метод ‘value'».

Комментарии:

1. вы пробовали ko.unwrap и позже передаете это.

2. Я не совсем понимаю, что вы предлагаете с later pass it . Я хочу обновить модель с текущим значением даты из datepicker. Пользователь внес правку в строку. Не уверен, как получить дату в модели при использовании пользовательской привязки.

3. да, это не будет обновляться, пожалуйста, проверьте опубликованный ответ. приветствия

Ответ №1:

Отдельные свойства объектов в моем массиве объектов не были наблюдаемыми.

Итак, когда я добавляю новый объект site в свой массив сайтов, мне нужно было сделать это:

               var Site = function(siteid, sitename, expirydate) {
                  this.siteid=siteid;
                  this.sitename = ko.observable(sitename);
                  this.expirydate = ko.observable(expirydate);

              }


              function SitesViewModel(){

                  var self=this;
                  self.sites = ko.observableArray([]);

                  self.sites.push( new Site ( ......) );

               }
  

так что valueAccessor() возвращает наблюдаемый объект, а не просто целое число, строку или дату, в зависимости от обстоятельств.

Ответ №2:

ну да, к сожалению, это не обновит модель по неизвестным причинам.

Но я заставил все работать для меня другим подходом.

С синтаксисом CSHTML :

 <input type="text"  data-bind="value:$data.CompletionDate,datePicker:true " />
  

Моменты, которые я заметил :
-В привязке данных, если вы удалите value и попытаетесь сохранить какую-либо пользовательскую привязку, как показано ниже, модель не получит обновления

 <input type="text"  data-bind="formatdate:$data.CompletionDate,datePicker:true " />
enter code here
  

-вместо этого я попытался использовать старомодный способ, оставаясь value нетронутым, и добавил Datepicker:true , который служит моей цели привязки и выбора даты.

Мой обработчик привязки Datepicker

 ko.bindingHandlers.datePicker = {
        init: function (element, valueAccessor) {
            var value = valueAccessor();
            var value = ko.utils.unwrapObservable(valueAccessor()); //ko.unwrap based on version you use 

            if (value amp;amp; typeof value === 'object') {
                $(element).datepicker(value);
            }
            else {
                $(element).datepicker(/* your default options here */);
            }
        }
}
  

Описанный выше подход может или не может решить вашу проблему, но он определенно приятен на вкус.