【问题标题】:Knockout js: Load model from JSONKnockout js:从 JSON 加载模型
【发布时间】:2014-07-05 22:17:02
【问题描述】:

我的模型有问题。我尝试从 JSON 加载模型,但效果不佳:( 我创建了级联选择列表。当我尝试将模型保存为 JSON,然后从保存的 JSON 中加载它时,会导致选择列表的值错误。

这是我的绑定:

<div id="condition-template" type="text/html">
  <div class="condition">
    <select class="textbox1" 
            data-bind="options: entarea, 
                       optionsText : &apos;displayName&apos;,
                       value: selectedArea " ></select>
    <select class="textbox1" 
            data-bind="options: Selectedfields, 
                       optionsText : &apos;fieldDisplayName&apos;,
                       value: selectedField "></select>
    <select class="textbox1" 
            data-bind="options: Selectedcomparisons, 
                       optionsText : &apos;comparsionDisplayName&apos;,
                       value: selectedComparison "></select>    
    <input class="textbox1" type="text" data-bind="value: value"></input>
    <button data-bind='click: save'>Save to JSON</button>
    <button data-bind='click: loadModel'>AddModel</button>
</p>

    <textarea data-bind='value: lastSavedJson' rows='5' cols='60' > </textarea>
    <inner type = "textarea" id="t_test"></inner>
  </div>
</div>   

我的模型是:

function Condition() {
 var self = this;
 var sqlArea = function(sqlAreaId, displayName) {
     this.displayName = ko.observable(displayName);
     this.sqlAreaId = ko.observable(sqlAreaId);
 };
 var field = function(fieldId, fieldDisplayName, sqlAreaId, fieldType) {
     this.fieldId = ko.observable(fieldId);
     this.fieldDisplayName = ko.observable(fieldDisplayName);
     this.sqlAreaId = ko.observable(sqlAreaId);
     this.fieldType = ko.observable(fieldType);
 };
 var comparison = function(comparsionId, comparsionDisplayName, fieldType) {
     this.comparsionId = ko.observable(comparsionId);
     this.comparsionDisplayName = ko.observable(comparsionDisplayName);
     this.fieldType = ko.observable(fieldType);
 };
 self.templateName = "condition-template";
 self.entarea = ko.observableArray([new sqlArea(1, "Client"), 
                                    new sqlArea(2, "Order")]);
 self.selectedArea = ko.observable();
 self.fields = ko.observableArray([new field( 1, "Name", 1, 1), 
                                   new field( 2, "Address", 1, 1), 
                                   new field( 3, "Phone number", 1, 1), 
                                   new field( 4, "Manager", 1, 1), 
                                   new field( 5, "Type", 1, 2), 
                                   new field( 6, "Order number", 2, 2), 
                                   new field( 7, "Sum", 2, 2), 
                                   new field( 8, "Date", 2, 3)]); 
 self.selectedField = ko.observable();
 self.comparisons = ko.observableArray([new comparison( 1,">=", 2),
                                     new comparison( 2,">", 2),
                                    new comparison( 3,"<=", 3), 
                                    new comparison( 4,"IN from date", 3),
                                    new comparison( 5,"IN from string", 1)
                                  ]);
 self.selectedComparison = ko.observable();
 //------------------------------------------------------------------------
 //Cascading select list
 self.Selectedfields = ko.dependentObservable(function () {
   var area = self.selectedArea(), sqlAreaId;
   if (area) {
      sqlAreaId = area.sqlAreaId();
      return ko.utils.arrayFilter(self.fields(), function(field) {
          return field.sqlAreaId() === sqlAreaId;
      });
   }
   return [];
 }, self);

 self.Selectedcomparisons = ko.dependentObservable(function() {
     var field = self.selectedField(), fieldType;
     if (field) {
       fieldType = field.fieldType();
       return ko.utils.arrayFilter(self.comparisons(),function(comparison) {
           return comparison.fieldType() === fieldType;
       });
     }
     return [];
 }, self);
 //-----------------------------------------------------------------------
 self.value = ko.observable(0);

 self.save = function() {
    self.lastSavedJson(JSON.stringify( ko.mapping.toJS(self), null, 2));
    var test = document.getElementById('t_test');
    test.innerHTML = (JSON.stringify( ko.mapping.toJS(self), null, 2));
 };
 self.lastSavedJson = ko.observable("");    
 self.loadModel = function() {
    var test = document.getElementById('t_test');
    var data = JSON.parse(test.innerHTML);

     ko.mapping.fromJS(data, {}, self);
     /* var viewModel = {};
        viewModel.model = ko.mapping.fromJS(data, {}, self);
                    self.updateFromModel(self, viewModel.model);*/
 };
}
ko.applyBindings(new Condition());

更新1: http://jsfiddle.net/3EWVR/2/

例如,当我选择 order/sum/>=/8 并将其保存到 JSON 时,我选择其他值(例如来自 string/0 的客户端/地址/in)并从 JSON 加载保存的数据模型,我希望获取原始输入 (order/sum/>=/8),但选择项中没有任何值,它会复制选择列表中的值。

【问题讨论】:

  • 你能做一个jsfiddle 样品吗
  • 你能澄清一下“不起作用”吗?它会给出错误吗?错误发生在哪里?
  • 例如,当我选择 order/sum/>=/8 并将其保存到 JSON 时,我选择其他值(例如 client/address/in from string/0)并从JSON,我希望得到原始输入(order/sum/>=/8),但选择项中没有任何值,它会复制选择列表中的值。

标签: json knockout.js mapping selectlist


【解决方案1】:

我认为问题的根源在于某些对象引用共享。考虑this fiddle 中描述的不同场景。

  • 但是,基本解释需要进一步澄清,因为 Order 模型会导致第一个 &lt;select&gt; 中的重复,而 Client 模型不会。这两种类型也会在第二个&lt;select&gt; 内造成重复。

  • 受影响的索引始终为 [0],这解释了为什么 Client 不重复。 0 的影响索引部分我还没有弄清楚

出于我尚未调查的原因,指定update callback

  ko.mapping.fromJS( init, {
      'selectedArea': {
          update: function (options) {
              return options.data;
          }
      }
  }, new Condition())

在 ko.mapping options 参数中似乎可以缓解这个问题。


另一种方法是引入optionsValue 绑定并在需要时通过a ko.utils function 查找对象

编辑

在仔细查看了options 在实际源中的应用与我缩小的示例之后,我仍然遇到了一些对象引用问题。所以我有applied my alternative approach

&lt;select&gt; 元素现在使用optionsValue 绑定参数。唯一影响源的地方是Selectedcomparisons。您必须查找该字段以访问 fieldType 属性。

var selectedField = ko.utils.arrayFirst(self.Selectedfields(), function (field) {
    return field.fieldId() === self.selectedField();
});

其他注意事项

  • 你在解析JSON,然后是ko.mapping.fromJS,我改了

    ko.mapping.fromJSON(self.lastSavedJson(), options, self)

  • dependentObservables 无法按定义写入,因此我将它们标记为已忽略

    var options = {ignore: []} var propertyNames = Object.keys(self); for(index in propertyNames){ var property = propertyNames[index] if(ko.isComputed(self[property])){ options.ignore.push(property) } };

【讨论】:

  • 我尝试在我的示例中添加选项,但它不起作用。 jsfiddle.net/3EWVR/8 。您能解释一下我的示例如何应用 ko.mapping 选项参数吗?
猜你喜欢
  • 2013-02-04
  • 2013-02-14
  • 1970-01-01
  • 2015-11-01
  • 2016-05-04
  • 2012-04-07
  • 2017-12-04
  • 2015-08-27
  • 1970-01-01
相关资源
最近更新 更多