Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
356 views
in Technique[技术] by (71.8m points)

javascript - How to update observable array element in knockoutjs?

I have following JavaScript array,

[{"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}] 

here is the relevent 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>

Then I have created observable array as,

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

Now I was able to get an specfic element using,

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

However when I change,

item.productQuantity = 20;

But UI is not updating. Tried also,

item.productQuantity(item.productQuantity)

But getting error productQuantity is not a function

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The above behavior is because only the array is an observable and not the individual elements within the array or the properties of each element.

When you do item.productQuantity = 20;, this will update the property but since it is not an observable, the UI does not get updated.

Similary, item.productQuantity(20) gives you an error because productQuantity is not an observable.

You should look at defining the object structure for each element of your array and then add elements of that type to your observable array. Once this is done, you will be able to do something like item.productQuantity(20) and the UI will update itself immediately.

EDIT Added the function provided by the OP :). This function will convert each property of the elements in an array to observables.

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

If you are unable to change that piece of code, you can also do something like observableItems.valueHasMutated(). However, this is not a good thing to do as it signals to KO and your UI that the whole array has changed and the UI will render the whole array based on the bindings.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...