[英]How to Refresh Knockout ViewModel Using Mapping Plugin
I have the following Knockout ViewModel: 我有以下Knockout ViewModel:
var EditorViewModel = function () {
var self = this;
self.addData = function (_data) {
ko.mapping.fromJS(_data, {}, self);
};
};
which is used as such: 可以这样使用:
var viewModel = new EditorViewModel();
viewModel.addData(model);
ko.applyBindings(viewModel);
For info, the data for viewModel.addData()
comes from an AJAX call. 有关信息, viewModel.addData()
的数据来自AJAX调用。
The View/ViewModel is populated with no problem the first time round when ko.applyBindings
is called. 第一次调用ko.applyBindings
时,View / ViewModel不会出现任何问题。 However, if I later pull new data from the server via AJAX and then call either: 但是,如果以后我通过AJAX从服务器提取新数据,然后调用以下任一方法:
viewModel.addData(someNewAjaxData)
or 要么
ko.mapping.fromJS(someNewAjaxData, {}, viewModel);
Then Knockout does not update the view with the new data. 然后,淘汰赛不会使用新数据更新视图。 Hopefully this is a trivial problem...?! 希望这是一个小问题...?!
KnockoutJS Mapping has the ability to specify a key for an item. KnockoutJS映射可以为项目指定键。 This lets KnockoutJS know when an item needs to be created versus updated. 这使KnockoutJS知道何时需要创建或更新项目。
var ItemViewModel = function(d){ var self = this; self.id = ko.observable(d.id); self.text = ko.observable(d.text); // We assign it when the object's created to demonstrate the difference between an // update and a create. self.lastUpdated = ko.observable(new Date().toUTCString()); } var EditorViewModel = function(){ var self = this; self.items = ko.observableArray(); self.addData = function(d){ ko.mapping.fromJS(d, { 'items': { 'create': function(o){ return new ItemViewModel(o.data); }, 'key': function(i){ return ko.utils.unwrapObservable(i.id); } } }, self); console.info(self); } self.addMoreData = function(){ self.addData({ 'items': [ {id:1,text:'Foo'}, {id:3,text:'Bar'} ] }); } } var viewModel = new EditorViewModel(); viewModel.addData({ items:[ {id:1,text:'Hello'}, {id:2,text:'World'} ] }); ko.applyBindings(viewModel);
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"/> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Hello, world!</h3> </div> <ul class="list-group"> <!-- ko foreach:items --> <li class="list-group-item"> <span class="text-muted" data-bind="text:id"></span> <span data-bind="text:text"></span> <span class="text-danger pull-right" data-bind="text:lastUpdated"></span> </li> <!-- /ko --> <li class="list-group-item" data-bind="visible:!items().length"> <span class="text-muted">No items.</span> </li> </ul> <div class="panel-footer"> <a href="#" data-bind="click:addMoreData">Update</a> </div> </div> </div> </div> </div>
Observe, in the attached snippet, how the first item's lastUpdated value is assigned when it's created, but is left unchanged when it's updated. 在随附的代码段中,观察创建第一项的lastUpdated值是如何分配的,但是在更新时将其保持不变。 This is because the mapper sees the ID already exists in items
and simply updated the properties. 这是因为映射器看到ID已存在于items
并且只是更新了属性。 But, for item with the id 3, a new model is created. 但是,对于ID为3的商品,将创建一个新模型。
All knockout bibdings were subscribed to the first created model. 所有剔除出价都订阅了第一个创建的模型。 You recreate the bound model on every ajax response. 您可以在每个ajax响应上重新创建绑定模型。 Your problem seems similar that was discussed in this stackoverflow article . 您的问题似乎与本stackoverflow文章中讨论的问题相似。 The same osbervable should be bound to the markup. 相同的osbervable应该绑定到标记。
Try this (may be you should support an empty model binding): 试试这个(也许你应该支持一个空的模型绑定):
// in the start of app
var observableModel = ko.observable();
ko.applyBindings(observableModel);
// on every ajax call
var viewModel = new EditorViewModel();
viewModel.addData(model);
observableModel(viewModel);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.