【问题标题】:How can I refresh or load JSON to my viewModel on Knockout JS with complex models如何在具有复杂模型的 Knockout JS 上将 JSON 刷新或加载到我的 viewModel
【发布时间】:2015-08-27 20:37:36
【问题描述】:

我从这里 fork 代码: http://kindohm.github.io/knockout-query-builder/

代码在客户端运行良好。 但是当我尝试将 viewModel 保存为 JSON,然后从服务器检索数据时,UI 根本不会刷新。

这是原始视图模型:

window.QueryBuilder = (function(exports, ko){

  var Group = exports.Group;

  function ViewModel() {
    var self = this;
    self.group = ko.observable(new Group());

        // the text() function is just an example to show output
    self.text = ko.computed(function(){
      return self.group().text();
    });
  }

  exports.ViewModel = ViewModel;
  return exports;

})(window.QueryBuilder || {}, window.ko);

我被添加到 viewModel 的下一个方法

self.Save = function () {
    console.log(ko.toJSON(self));
}

将此按钮添加到视图中

<input type="submit" value="Save" data-bind="click: Save"/>

这是组视图模型:

window.QueryBuilder = (function(exports, ko){

  var Condition = exports.Condition;

  function Group(data){
    var self = this;

    self.templateName = data.templateName;
    self.children = ko.observableArray(data.children);
    self.logicalOperators = ko.observableArray(data.logicalOperators);
    self.selectedLogicalOperator = ko.observable(data.selectedLogicalOperator);

    // give the group a single default condition
    self.children.push(new Condition());

    self.addCondition = function(){
        self.children.push(new Condition());
    };

    self.addGroup = function(){
        self.children.push(new Group());
    };

    self.removeChild = function(child){
        self.children.remove(child);
    };

    // the text() function is just an example to show output
    self.text = ko.computed(function(){
      var result = '(';      
      var op = '';
      for (var i = 0; i < self.children().length; i++){
        var child = self.children()[i];
        console.log(child);
        result += op + child.text();
        op = ' ' + self.selectedLogicalOperator() + ' ';
      }
      return result += ')';
    });
  }

  exports.Group = Group;
  return exports;

})(window.QueryBuilder || {}, window.ko);

所以当我按下“保存”按钮时,控制台会显示来自这个 viewModel 的 JSON,这里一切正常。

这是返回的 JSON:

{"group":{"templateName":"group-template","children":[{"templateName":"condition-template","fields":["Points","Goals","Assists","Shots","Shot%","PPG","SHG","Penalty Mins"],"selectedField":"Points","comparisons":["=","<>","<","<=",">",">="],"selectedComparison":"=","value":0,"text":"Points = 0"},{"templateName":"condition-template","fields":["Points","Goals","Assists","Shots","Shot%","PPG","SHG","Penalty Mins"],"selectedField":"Points","comparisons":["=","<>","<","<=",">",">="],"selectedComparison":"=","value":0,"text":"Points = 0"},{"templateName":"condition-template","fields":["Points","Goals","Assists","Shots","Shot%","PPG","SHG","Penalty Mins"],"selectedField":"Points","comparisons":["=","<>","<","<=",">",">="],"selectedComparison":"=","value":0,"text":"Points = 0"}],"logicalOperators":["AND","OR"],"selectedLogicalOperator":"AND","text":"(Points = 0 AND Points = 0 AND Points = 0)"},"text":"(Points = 0 AND Points = 0 AND Points = 0)"}

我做了一个简单的 hack 来避免连接到服务器,所以我将那个 json 复制并粘贴到 load 事件上并发送到 viewModel 的构造函数:

  var vm;
  window.addEventListener('load', function(){ 
    var json = {"group":{"templateName":"group-template","children":[{"templateName":"condition-template","fields":["Points","Goals","Assists","Shots","Shot%","PPG","SHG","Penalty Mins"],"selectedField":"Points","comparisons":["=","<>","<","<=",">",">="],"selectedComparison":"=","value":0,"text":"Points = 0"},{"templateName":"condition-template","fields":["Points","Goals","Assists","Shots","Shot%","PPG","SHG","Penalty Mins"],"selectedField":"Points","comparisons":["=","<>","<","<=",">",">="],"selectedComparison":"=","value":0,"text":"Points = 0"},{"templateName":"condition-template","fields":["Points","Goals","Assists","Shots","Shot%","PPG","SHG","Penalty Mins"],"selectedField":"Points","comparisons":["=","<>","<","<=",">",">="],"selectedComparison":"=","value":0,"text":"Points = 0"}],"logicalOperators":["AND","OR"],"selectedLogicalOperator":"AND","text":"(Points = 0 AND Points = 0 AND Points = 0)"},"text":"(Points = 0 AND Points = 0 AND Points = 0)"}; 

    vm = new QueryBuilder.ViewModel(json);  
    ko.applyBindings(vm);           
  }, true);

然后我修改viewModel来获取json参数

window.QueryBuilder = (function(exports, ko){

  var Group = exports.Group;

  function ViewModel(json) {
    var self = this;
    self.group = ko.observable(json.group);

        // the text() function is just an example to show output
    self.text = ko.computed(function(){
      return self.group().text();
    });
    self.Save = function () {
        console.log(ko.toJSON(self));
    }   
  }

  exports.ViewModel = ViewModel;
  return exports;

})(window.QueryBuilder || {}, window.ko);

当我刷新 index.html 时,视图永远不会正确加载并在 JS 控制台上显示此错误:

TypeError: self.group(...).text is not a function
return self.group().text();

有人知道我的错误在哪里吗?


我遇到的最后一个问题与孩子的 text() 函数有关。 我使用 try/catch 来解决这个问题。因此,当 viewModel 是新的时,它具有 text() 函数,但是当它被加载时, text() 不存在,所以我直接从“text”字段中获取值。

try {
    result += op + child.text();
}
catch(err) {
    result += op + child.text;
}           

问题出在 Group 类和 Condition 类上。 这是当前有效的代码:

window.QueryBuilder = (function(exports, ko){

  var Condition = exports.Condition;

  function Group(data){
    var self = this;

    self.templateName = data.templateName;
    self.children = ko.observableArray(data.children);
    self.logicalOperators = ko.observableArray(data.logicalOperators);
    self.selectedLogicalOperator = ko.observable(data.selectedLogicalOperator);

    // give the group a single default condition
    self.children.push(new Condition(data.children[0]));

    self.addCondition = function(){
        self.children.push(new Condition());
    };

    self.addGroup = function(){
        self.children.push(new Group());
    };

    self.removeChild = function(child){
        self.children.remove(child);
    };

    // the text() function is just an example to show output
    self.text = ko.computed(function(){
      var result = '(';      
      var op = '';
      for (var i = 0; i < self.children().length; i++){
        var child = self.children()[i];

        try {
            result += op + child.text();
        }
        catch(err) {
            result += op + child.text;
        }           

        op = ' ' + self.selectedLogicalOperator() + ' ';
      }
      return result += ')';
    });
  }

  exports.Group = Group;
  return exports;

})(window.QueryBuilder || {}, window.ko);

window.QueryBuilder = (function(exports, ko){

  function Condition(data){
    var self = this;

    self.templateName = data.templateName;

    self.fields = ko.observableArray(data.fields);
    self.selectedField = ko.observable(data.selectedField);

    self.comparisons = ko.observableArray(data.comparisons);

    self.selectedComparison = ko.observable(data.selectedComparison);

    self.value = ko.observable(data.value);

    // the text() function is just an example to show output
    self.text = ko.computed(function(){
      return self.selectedField() + 
        ' ' +
        self.selectedComparison() + 
        ' ' + 
        self.value();
    });
  }

  exports.Condition = Condition;
  return exports;

})(window.QueryBuilder || {}, window.ko);

【问题讨论】:

    标签: javascript json mvvm knockout.js


    【解决方案1】:

    您应该采用与加载self.group = ko.observable(new Group()); 时类似的方法而不是self.group = ko.observable(json.group);,但这次将json.group 数据传递到Group

     self.group = ko.observable(new Group(json.group));
    

    我看不到 Group 的定义位置,但您应该确保它能够处理您现在传入的 JSON 并将其转换为 observables。

    【讨论】:

    • 我只是检查了该代码,但不起作用。我已经使用组代码编辑了我的原始问题。谢谢。
    • 不,错误已经消失。但 UI 永远不会刷新或加载 JSON。
    • 好的,听起来您必须编辑 Group 类。我现在没有时间处理它,但它需要处理你传入的 json 并用你传入的值初始化 observables。
    • 好吧,我对 Group 类做了一些更改,代码就可以工作了。但如果我不评论这一行: result += op + child.text();代码不起作用。错误是:TypeError: child.text is not a function result += op + child.text();这个方法在孩子上调用,但是不起作用,你知道为什么吗?
    • 我更改了 text() 函数上的代码并且运行良好。谢谢。
    猜你喜欢
    • 2014-07-05
    • 2015-03-29
    • 2015-11-01
    • 1970-01-01
    • 2012-02-29
    • 1970-01-01
    • 2021-07-13
    • 2014-01-12
    • 1970-01-01
    相关资源
    最近更新 更多