Search code examples
knockout.jsko.observablearray

Observable Array UI not being updated when an item is changed


this is inside my view model.

self.Notifications = ko.observableArray(); // loaded by ajax

self.MarkAsFlagged = function(item) { //updates the item in Notifications
        console.log('MarkAsFlagged');
        var index = self.Notifications.indexOf(item);
        console.log(index);

        var flagStatus = item.Flagged; // current flagstatus
        item.Flagged = !flagStatus; // set true if false and viceversa

        flagStatus = !flagStatus;// set true if false and viceversa
        self.Notifications.replace(self.Notifications()[index], item);
}

this is my html

<ul data-bind="foreach: Notifications "  >
 <li>
   <span data-bind="text: Name" style="font-weight: bold;"></span>       
   <div style="float: right; width:15px;">
       <input type="image" id="" data-bind="click:function(){$parent.MarkAsFlagged($data)},css: {flagged: Flagged==true, unFlagged: Flagged==false }" style='float:right;padding-right:3px;' />
   </div>
 </li>
</ul>

when i click the MarkedAsFlagged and replace the item on self.Notifications() the ui is not changing.

the ui only responses when i remove any item from the array. please help here.


Solution

  • Item props in Notifications array is not observable. So, when you change it in MarkAsFlagged, ui is not updated. You should create own model for item with observable props:

    function ItemModel(data) {
        var self = this;
        self.Name = ko.observable(data.Name);
        self.Flagged = ko.observable(data.Flagged);
    }
    
    function ViewModel() {
        var self = this;
        self.Notifications = ko.observableArray();
    
        self.loadNotifications = function() {
           // loading data...
    
           var itemModels = _.map(data, function (item) {
               return new ItemModel(item);
           }); 
           ko.utils.arrayPushAll(self.Notifications(), itemModels);
        }
    }