2013-11-29 4 views
2

Рассмотрим следующие свойства внутри ViewModelKnockout и наблюдаемый массив несовпадение

self.allValues = ko.observableArray(); 
self.selectedValues = ko.observableArray(); 

На редактирования, selectedValues содержит значения, поступающие из базы данных. Вот в чем проблема: selectedValues содержит элементы, не включенные в allValues, но они не те же экземпляры. Они одинаковы с точки зрения значений свойств, но на самом деле являются разными объектами.

Это приводит к тому, что каждый раз, когда нокаут использует indexOf над allValues, используя объекты от selectedValues, всегда не удается найти объект.

Я использую selectedValues на привязке checked, но не проверяет правильные элементы, включенные в этот массив.

<div class="vars-list" data-bind="foreach: allValues"> 
    <input type="checkbox" data-bind="checkedValue: $data...(etc) 
     checked: selelectedValues" /> 
</div> 

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

+0

проверяемого связывание внутренне использует 'indexOf', чтобы проверить, какой элемент выбран, и это сравнение не настраивается. Таким образом, у вас есть два варианта создания пользовательской привязки, основанный на привязке 'checked', где вы можете провести свое сравнение. Или когда вы загружаете свой массив 'selectedValues' вместо создания нового объекта, вы просматриваете элемент из' allValues'. Таким образом, 'selectedValues' будет содержать экземпляры, которые находятся в массиве' allValues'. http://jsfiddle.net/NQYW9/ – nemesv

+0

@nemesv: Я слежу за поиском, но кажется немного грязным, поэтому я хотел узнать альтернативный вариант. Я буду проверять пользовательскую привязку. Благодаря! – StackOverflower

+0

Функция нокаута: позволяет настроить сравнение. Я согласен с тем, что подход поиска грязный. Я на самом деле боролся с аналогичной ситуацией с выпадающим списком, и меня направили на этот пост. http://stackoverflow.com/questions/20411739/knockout-js-setting-selectedoption-to-an-object?noredirect=1#comment30493376_20411739 – Airn5475

ответ

5

Использование специального связывания - один из способов. Ниже приведен вариант привязки checked, который использует функцию сравнения.

ko.bindingHandlers.checkedInArray = { 
    init: function (element, valueAccessor, allBindings) { 
     ko.utils.registerEventHandler(element, "click", function() { 
      var observable = valueAccessor(), 
       array = observable(), 
       checkedValue = allBindings.get('checkedValue'), 
       isChecked = element.checked, 
       comparer = allBindings.get('checkedComparer'); 

      for (var i = 0, n = array.length; 
       i < n && !comparer(array[i], checkedValue); 
       ++i) { } 

      if (!isChecked && i < n) { 
       observable.splice(i, 1); 
      } else if (isChecked && i == n) { 
       observable.push(checkedValue); 
      } 
     }); 
    }, 
    update: function (element, valueAccessor, allBindings) { 
     var array = valueAccessor()(), 
      checkedValue = allBindings.get('checkedValue'), 
      comparer = allBindings.get('checkedComparer'); 

     for (var i = 0, n = array.length; 
      i < n && !comparer(array[i], checkedValue); 
      ++i) { } 

     element.checked = (i < n); 
    } 
}; 

jsFiddle: http://jsfiddle.net/mbest/4mET9/

+0

Эй, спасибо! Я буду тестировать это, как только смогу, и дам вам знать, как это происходит. – StackOverflower

+0

Этот код спас меня сегодня. Не могу поблагодарить вас за это! – dgarbacz

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