【问题标题】:Knockout Master/Detail object from JSON with template and function使用模板和函数从 JSON 中剔除 Master/Detail 对象
【发布时间】:2013-04-08 07:18:43
【问题描述】:

我最近开始使用 Knockout,大多数事情都非常容易完成。然而,这个让我有点难过,希望有人能提供一些帮助。我正在通过序列化具有 Master/Detail 结构的 JSON 对象来创建我的 Knockout 模型,我怀疑这会导致我的一些问题。我可以绑定/呈现记录的主部分,并且可以使用 foreach 模板绑定和呈现详细信息。但是,在我的场景中,我希望用户从子列表中选择要编辑的详细记录。问题是我无法让选择起作用。我正在触发 click 事件,并且似乎我的详细记录正在传递给我的事件 - 除了我无法读取属性的值。在提琴手看来,通过的对象是事件的函数调用。目前还不确定。所以,这是我的设置

我的 JSON

{
"Height":"250",
"Width":"200",
"Speed":"700",
"Pause":"4",
"ShowItems":"1",
"Animation":"fade",
"MousePause":"true",
"IsPaused":"false",
"Direction":"up",
"DataItems":[{
     "OrderId":1,
     "ItemHtml":"This is item 1"
  },{
     "OrderId":2,
     "ItemHtml":"This is item 2"
  },{"
     OrderId":3,
    "ItemHtml":"This is item 3"
  }]
}

Javascript 序列化 JSON 对象

var viewModel = {
  vmRotator: ko.mapping.fromJSON(jsonObj)

  //-- THIS IS WHERE I THINK THE PROBLEM IS
  , selectRotatorItem: function (item) {
    //alert(item.OrderId); // THIS DOES NOT WORK
    console.log(item);
  }
}
ko.applyBindings(viewModel);

//-- hookup the click event for templated items
$("#rotatorItems").on("click", ".sel", function () {
  var data = ko.dataFor(this);
  viewModel.selectRotatorItem(data); //-- call to object function
});     

HTML 显示项目,提供点击按钮

<table id="rotatorList" width="100%" border="0" cellspacing="0" cellpadding="2">
  <tbody id="rotatorItems" data-bind="template: { foreach: vmRotator.DataItems }">
  <tr>
    <td style="width: 20px;">
      <input type="button" class="sel" value="Select" />
      <span data-bind="text: OrderId"></span>
    </td>
    <td style="width: 90%;" data-bind="text: ItemHtml"></td>
  </tr>
  </tbody>
</table>

我可以说这一切正常。我的事件正在被调用,但是当我在控制台中查看结果时,它看起来像是函数的文本而不是值。

在函数中:

, selectRotatorItem: function (item) {
  //alert(item.OrderId); // THIS DOES NOT WORK
  console.log(item);
}

alert(item.OrderId) 显示:

"function d(){if(0<arguments.length){if(!d.equalityComparer||!d.equalityComparer(c,arguments[0]))d.H(),c=arguments[0],d.G();return this}b.r.Wa(d);return c}"

而不是像 1 或 2 这样的数字,即订单 ID 的值。不知道为什么会这样,但我做错了什么。

我通过查看几个与我正在做的类似的示例将这段代码拼凑在一起。我可能会以完全错误的方式解决这个问题,但我认为我只是缺少一些简单的东西。我相信那里的一些 Javasctipt 大神可以轻松地看到我看不到的东西,所以我很感激你的帮助。


为了回应 Rune 对我最初问题的回答,这是最终版本的工作

用于构建绑定的 Javascript 代码

//-- define models: master and detail modesl
var viewRotatorItemModel = {
  'Height': ko.observable(),
  'Width': ko.observable()
};

var viewRotatorModel = {
  'Height': ko.observable(),
  'Width': ko.observable(),
  'Speed': ko.observable(),
  'ShowItems': ko.observable(),
  'Animation': ko.observable(),
  'IsPaused': ko.observable(),
  'Direction': ko.observable(),
  'UseEditor': ko.observable(),
  'HtmlData': ko.observable(),
  'DataItems': {
        create: function (options) {
        return new viewRotatorDataItem(options.data);
      }
    }
};

//-- define objects around models
var viewRotatorDataItem = function (data) {
  var self = this;
  //--> IMPORTANT TO USE fromJS as JSON is already an object
  ko.mapping.fromJS(data, viewRotatorItemModel, self); 
  self.selectItem = function () {
    alert("item with id " + self.OrderId() + " clicked");
  };
};

var ViewModel = function (data) {
    var self = this;
    //--> IMPORTANT TO USE fromJSON as incoming object is JSON text
    ko.mapping.fromJSON(data, viewRotatorModel, self);
};

...
...

//-- create objects when ready
    vmRotator = new ViewModel(jsonObj);
    ko.applyBindings(vmRotator);    

显示主/明细项的 HTML

<h4>Main Items</h4>
<input type="text" id="wc_Height" data-bind="value: vmRotator.Height" />

<input type="text" id="wc_Width" data-bind="value: vmRotator.Width" />

<h3>Detail Items</h3>
<table id="rotatorList" width="100%" border="0" cellspacing="0" cellpadding="2">
  <tbody id="rotatorItems" data-bind="template: { foreach: vmRotator.DataItems }">
  <tr>
    <td style="width: 20px;"> 
      <input type="button" value="Select" data-bind="click: selectItem" />
      <span data-bind="text: OrderId"></span>
    </td>
    <td style="width: 90%;" data-bind="text: ItemHtml"></td>
  </tr>
</tbody>
</table>

【问题讨论】:

    标签: jquery json knockout.js


    【解决方案1】:

    我建议您使用敲除映射向您可以从标记调用的数据项添加自定义功能。 (我为你创建了一个工作JSBin

    您的初始数据保持不变,您的 javascript 变为:

    var DataItem = function(data) {
        var self = this;
        ko.mapping.fromJS(data, {}, self);
        // add custom functionality to each data item here
        // here an alert is added that can be called via 'selectItem' in markup
        self.selectItem = function(){
          alert("item with id " + self.OrderId() + " clicked");
        }; 
    };
    
    var viewModelMapping = {
        'DataItems': {
         create: function(options) {
            return new DataItem(options.data);
            }
        }
    };
    
    var ViewModel = function(data) {
        var self = this;
        ko.mapping.fromJS(data, viewModelMapping, self);
    };
    
    var vm = new ViewModel(initialData);
    $(document).ready(function () {
        ko.applyBindings(vm);   
    }); 
    

    您的 HTML 表格变成了(为清晰起见删除了样式):

    <table>
      <tbody data-bind="foreach: DataItems">
      <tr>
          <td">
            <input type="button" value="Select" data-bind="click: selectItem" />
            <span data-bind="text: OrderId"></span>
          </td>
          <td data-bind="text: ItemHtml"></td>
        </tr>
      </tbody>
    </table>
    

    您可以在使用“create”自定义对象构造使用“update”自定义对象更新部分阅读更多关于自定义映射对象的信息here

    【讨论】:

    • Rune,感谢您抽出宝贵时间提供如此详尽的答案。通过一些调整,我现在可以在我的代码中使用它,并且我对它的工作方式/原因有了更好的理解。我也喜欢它如何让我清楚地定义我的模型。似乎有很多我仍然不知道的使用 Knockout 的不同方式。
    【解决方案2】:

    我认为问题是你应该放弃#rotatorItems 的jQuery 绑定,并在.sel 按钮上使用'click' 绑定:

    请看这个小提琴:

    http://jsfiddle.net/EKXKF/2/

    主要变化:

    <tbody id="rotatorItems" data-bind="foreach: vmRotator.DataItems">
      <tr>
        <td style="width: 20px;">
          <input type="button" class="sel" value="Select" data-bind="click: $root.selectRotatorItem" />
          <span data-bind="text: OrderId"></span>
        </td>
        <td style="width: 90%;" data-bind="text: ItemHtml"></td>
      </tr>
    </tbody>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-02
      • 2016-06-23
      • 2013-10-17
      • 2012-10-31
      • 2012-11-10
      • 1970-01-01
      • 2015-11-12
      • 1970-01-01
      相关资源
      最近更新 更多