2013-02-19 3 views
10

У меня следующий массив JavaScript,Как обновить наблюдаемый элемент массива в knockoutjs?

[{"unitPrice": 2499,"currency":"$","productId":1,"retailerId":1,"productName":"XX ","formattedPrice":"$ 2,499","productImage":"Images/2012_08_12_00_45_39_4539.jpg","productQuantity":"9","totalPrice":19992}, 
{"unitPrice": 4999,"currency":"$","productId":2,"retailerId":1,"productName":"XX","formattedPrice":"$ 4,999","productImage":"Images/2012_08_12_00_46_45_4645.jpg","productQuantity":2,"totalPrice":9998}, 
{"unitPrice":4555,"currency":"$","productId":1,"retailerId":1,"productName":"XXXXX","formattedPrice":"$ 4,555","productImage":"Images/2013_02_12_10_57_49_5749_9868.png","productQuantity":3,"totalPrice":13665}] 

вот Релевент HTML,

<table> 
<tbody data-bind="foreach: $root"> 
        <tr> 
         <td><img width="45" height="45" alt="" data-bind="attr:{src: productImage}"/></td> 
         <td><span data-bind="html: productName"></span></td> 
         <td><span data-bind="html: formattedPrice"></span></td> 
         <td><input type="number" class="quantity" data-bind="value: productQuantity, attr:{'data-id': productId }" /></td> 
         <td><span data-bind="html: totalPrice"></span></td> 
        </tr> 
       </tbody> 
</table> 

Затем я создал наблюдаемую массив как,

observableItems = ko.observableArray(items); 
ko.applyBindings(observableItems); 

Теперь я был в состоянии получить с использованием параметров,

 var obj = ko.utils.arrayFirst(list(), function (item) { 
      return item.productId === id; 
     }); 

Однако когда я меняю,

item.productQuantity = 20; 

Но UI не обновляется. Пытались также,

item.productQuantity(item.productQuantity) 

Но получение productQuantity ошибок не является функцией

ответ

17

выше поведение, потому что только массив является наблюдаемой, а не отдельные элементы в массиве или свойства каждого элемента.

Когда вы сделаете item.productQuantity = 20;, это обновит свойство, но поскольку оно не является наблюдаемым, пользовательский интерфейс не обновляется.

Similary, item.productQuantity(20) дает вам ошибку, поскольку productQuantity не является наблюдаемым.

Вы должны посмотреть на определение структуры объекта для каждого элемента вашего массива, а затем добавить элементы этого типа в свой наблюдаемый массив. Как только это будет сделано, вы сможете сделать что-то вроде item.productQuantity(20), и пользовательский интерфейс немедленно обновится.

EDIT Добавлена ​​функция, предоставляемая OP :). Эта функция преобразует каждое свойство элементов в массив в наблюдаемые.

function convertToObservable(list) 
{ 
    var newList = []; 
    $.each(list, function (i, obj) { 
     var newObj = {}; 
     Object.keys(obj).forEach(function (key) { 
      newObj[key] = ko.observable(obj[key]); 
     }); 
     newList.push(newObj); 
    }); 
    return newList; 
} 

END EDIT

Если вы не в состоянии изменить этот код, вы также можете сделать что-то вроде observableItems.valueHasMutated(). Однако это не очень хорошо, поскольку он сигнализирует KO и вашему пользовательскому интерфейсу, что весь массив изменился, и пользовательский интерфейс отобразит весь массив на основе привязок.

+0

observableItems.valueHasMutated() не работает – user960567

+0

Получил его, добавив эту функцию, function conve rtToObservable (list) { var newList = []; $.каждый (список, функция (i, obj) { var newObj = {}; Object.keys (obj) .forEach (функция (ключ) { новыйObj [ключ] = ko.observable (obj [ключ]); }); новыйList.push (newObj); }); return newList; } – user960567

+0

Пожалуйста, поставьте этот внутренний ответ. – user960567

9

Вы можете легко использовать ko.mapping плагин для преобразования объекта становится наблюдаемым: http://knockoutjs.com/documentation/plugins-mapping.html

Преобразования регулярной JS объекта в наблюдаемую сущность:

var viewModel = ko.mapping.fromJS(data); 

Преобразование наблюдаемого объекта в обычный объект JS:

var unmapped = ko.mapping.toJS(viewModel); 
+0

ok, но если наблюдаемый массив представляет собой массив из многих объектов, вы бы обновили индивидуальное свойство одного объекта в массиве с помощью этого метода? – Andrew

+0

Вам нужно точно знать, какой объект будет обновляться в вашем массиве, поэтому вы преобразовываете этот конкретный объект в наблюдаемый. Это также полезно для производительности. –

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