Knockout js:从JSON加载模型

时间:2014-05-17 14:42:45

标签: json knockout.js mapping selectlist

我的模型有问题。我尝试从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());

UPDATE1: http://jsfiddle.net/3EWVR/2/

例如,当我选择order / sum /&gt; = / 8并将其保存为JSON然后我选择其他值(例如来自string / 0的client / address / in)并从JSON加载保存的数据模型,我期待获取原始输入(order / sum /&gt; = / 8)但是select item中没有任何值,它会在选择列表中显示值。

1 个答案:

答案 0 :(得分:1)

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

  • 但是,该基本说明需要进一步说明,因为Order模型会导致第一<select>内的重复,而Client模型则不会。这两种类型也会导致第二个<select>内的重复。

  • 受影响的索引始终为[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

<select>元素现在使用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) } };