Knockout JS update view from json model

久未见 提交于 2020-07-20 03:48:06

问题


Please refer to this question as it helped solving 50% of my issue:

Knockout Mapping reading JSON

the other 50% of issue is updating view, if you call ko.applyBindings(viewModel); twice, you get an error Uncaught Error: You cannot apply bindings multiple times to the same element.

No one online ever proposed a solution to this, even on the official knockout site they mentioned:

// Every time data is received from the server:
ko.mapping.fromJS(data, viewModel);

which is not working either. Anyone knows what the proper method is to update my view each time I fetch new data, knowing that the view is already initialized via ko.applyBindings(viewModel);?

Edit:

HTML :

<select class="input-short artist-list" data-bind="foreach: model">
   <option value="1" selected="selected" data-bind="text: name"></option>                                           
 </select>  

JS

var viewModel = {
        model: ko.observableArray()            
    };


$(window).load(function(){
    fetchArtists();  

  })
function fetchArtists() //this function fetches all artists
{
     // load data
       $.post( "../db/fetch/", { table: "artists"})
          .done(function( data ) {
          //  artists=JSON.parse(data);
          data=JSON.parse(data);//data is array of objects e.g [{name:"xxx"},{name:"yyy"}]   
          artists.model = ko.mapping.fromJS(data);         
          ko.applyBindings(artists);      
          });

}

回答1:


In knockout, a ViewModel is applied to the view once (applyBindings). Everytime the observables bind with data-bind are updated (e.g. assigning new data to them), the view is re-rendered. Your mistake is binding a non-observable (model) and re-defining artists.model with every function call.

You should do it the following way:

var viewModel = {
    artists: ko.observableArray()          
};


$(window).load(function(){
    fetchArtists();  
});

function fetchArtists()
{
     // load data
       $.post( "../db/fetch/", { table: "artists"})
          .done(function( data ) {
              viewModel.artists(JSON.parse(data)); // assign new values to artists observable          
       });
}

HTML

<select class="input-short artist-list" data-bind="foreach: artists">
   <option value="1" selected="selected" data-bind="text: name"></option>                                           
</select>

<script>
    ko.applyBindings(viewModel); // apply ViewModel
</script>



回答2:


This should do what you want to do:

JS

var viewModel = {
    model: ko.observableArray()            
};

$(window).load(function(){
    ko.applyBindings( viewModel );
    fetchArtists();  
})

function fetchArtists()
{
     $.post( "../db/fetch/", { table: "artists" } ).done(function( data ) {
          ko.mapping.fromJSON( data, {}, viewModel.model ); 
     });

}

As @SVSchmidt mentioned, you can only call ko.applyBindings() once per element. So you will ko.applyBindings once (on page load/ready most likely) and then either update the observableArray (model) directly or use the mapping plugin.

Updating the observableArray (model) directly will mean the values will be plain values. But if you wanted those values to be observable, then ko.mapping will be appropriate.

So to use the mapping plugin, you can call ko.mapping.fromJS or ko.mapping.fromJSON if you have raw JSON data.

The parameters for fromJS and fromJSON will be, in order:

  • incoming data that you want to map (in your case data)
  • options object that you can use to control mapping (empty object for now)
  • destination viewmodel or viewmodel property that you want to update (in your case viewModel.model

Here is a working demo that shows you how this works in action: http://plnkr.co/edit/4g1izaLYraBjganjX2Ue?p=preview



来源:https://stackoverflow.com/questions/31896922/knockout-js-update-view-from-json-model

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!