Knockout.js Workflow with Mapping plugin

◇◆丶佛笑我妖孽 提交于 2019-12-13 02:00:18

问题


I'm not sure I understand the workflow Knockout.js follows internally. I have a ViewModel that is defined dynamically, using the mapping plugin. Its shape is:

{ current: { foo: 'foo', bar: 'bar', id: 0 }
, ids:     [1,2,3,4,5] 
}

Each of those ids corresponds to a value that can belong in current. Now, the complication comes in because in the initial ajax request to populate my viewModel, the server responds with current: null. I have written code to take the first id out of the list of ids and run another ajax query to populate current. That looks like this:

var ViewModel = function (data) {
  var self = this;
  ko.mapping.fromJS(data, {}, self);

  self.head = function () {
    if (self.promptIds().length != 0) {
      var nextId = _.head(self.promptIds());
      self.promptIds(_.tail(self.promptIds()));
      $.getJSON("my-url" + "/" + nextId, function (data) {
        self.current(ko.mapping.fromJS(data));
      });
    }
  }
}


$('document').ready ( function () {
  $.getJSON("view-model-route", function (data) {
    viewModel = new ViewModel(data);
    viewModel.head();
    ko.applyBindings(viewModel);
  });
});

Notice that in the second block, I create a new ViewModel object and I call head() on it. Once the viewModel.current() object is populated, I call ko.applyBindings on the complete viewModel. I can confirm that when all the dust settles, viewModel.current is not null. But I am still getting the error:

Uncaught TypeError: Unable to parse bindings.
  Bindings value: text: current().foo
  Message: Cannot read property 'foo' of null

Am I trying to do something Knockout wasn't designed to do? Do I need another layer of abstraction? How would you approach this situation?


回答1:


The bindings are first evaluated when you call ko.applyBindings.

So if your current property contains null by that time then this it is normal that you get an Cannot read property 'foo' of null exception.

There are multiple solution to this problem:

  • Initialize current with an empty object, so the current().foo will be parsed correctly (but its value be undefined):

    viewModel = new ViewModel(data);
    viewModel.head();
    viewModel.current({});
    ko.applyBindings(viewModel);
    
  • You can add an extra condition in your binding to check that current has some value:

    <input type="text" data-bind="value: current() && current().foo" />
    
  • Or probably the best and most recommended option is to use the with binding if you are dealing with nested proeprties:

    <!-- ko with: current -->
        <input type="text" data-bind="value: foo" />
    <!-- /ko -->
    

Demo JSFiddle.



来源:https://stackoverflow.com/questions/24000573/knockout-js-workflow-with-mapping-plugin

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