【问题标题】:Passing in an observableArray as a function parameter传入 observableArray 作为函数参数
【发布时间】:2013-03-01 19:24:37
【问题描述】:

我想要实现的目标: 一个带有一个文本输入字段(名称)的表单,两个带有一些选项(类型和列)的选择字段,带有一个提交按钮,该按钮创建一个小部件,其标题设置为名称,数据类型设置为类型和列 - 它的位置这页纸。

在这种情况下,类型在视图中定义了几个不同的选项,它的工作原理很花哨,所以我现在不会详细说明我是如何让它工作的。

到目前为止,我有一个包含三列的页面,每一列都是自己的 observableArray - 就像这样:

self.col0 = ko.observableArray([]);
self.col0.id = 'col0'

col1 和 col2 也是如此。我的目标是让选择字段指向这些数组。至少这是我认为我需要做的。

我有一个 createWidget 函数,它查看 DOM 中的 Name 和 Type 值(如果我在这里错了,请纠正我,这是我用 KnockOut 创建的第一件事)并从中创建一个新的 Widget数据 - 像这样:

var Widget = function(name, type) {
  var self  = this;
  self.name = name;
  self.type = type;
}; 

var ViewModel = function() {
  var self = this;
  self.newWidgetName = ko.observable();
  self.newType       = ko.observable();

// Unrelated code in between

self.createWidget = function(target) {
  newName = self.newWidgetName();
  newType = self.newType();
  widget  = new Widget(newName, newType);
  target.unshift(widget)
  self.newWidgetName("");
};

DOM 中的输入/选择元素

input.widget-name type="text" placeholder="wName" data-bind="value: newWidgetName"

select data-bind="value: newType"
  option value="calendar" Calendar
  option value="article"  Article
  option value="document" Document

select.colPick data-bind="value: colPick"
  option value="col0" Column 1
  option value="col1" Column 2
  option value="col2" Column 3

还有我的 createWidget 函数的点击处理程序 - 像这样:

a.btn.create-widget data-bind="click: function(){ createWidget(col0); }"

Shazam,它有效!

但是,这只会将新小部件输出到第一个列 (col0),它不会考虑列选择字段的值,也不会将新小部件移到正确的列中。经过反复试验,我得到的错误几乎可以归结为:

1)“无法调用未定义的方法unshift”

2) "未捕获的 TypeError: Object function observable() .... has no method 'unshift'

所以到目前为止,代码看起来像上面的示例,无论如何它并不理想,但不同的列与可淘汰排序相关联,如果必须废弃此功能,这并不是什么大问题。用户仍然可以将小部件从 col0 移动到 col2,反之亦然。

如果有人有资源可以为我指明正确的方向,或者他们袖手旁观的答案 - 请随时分享!

一切顺利,卡斯。

编辑:Tyrsius 的后续问题

使用您提供的代码,我现在可以在选择框中使用三列,但是在将小部件输出到视图时我有点挣扎。

使用我之前的代码,视图如下所示:

<div class="cols">
  <div class="col col-25">
    <ul data-bind="sortable: { template: 'widgetTmpl', data: col0, afterMove: $root.widgetData }">
    </ul>
  </div>
  <div class="col col-50">
    <ul data-bind="sortable: { template: 'widgetTmpl', data: col1, afterMove: $root.widgetData }">
    </ul>
  </div>
  <div class="col col-25">
    <ul data-bind="sortable: { template: 'widgetTmpl', data: col2, afterMove: $root.widgetData }">
    </ul>
  </div>
</div>

我现在的工作是这样的:

<div data-bind="foreach: columns">
  <div data-bind="foreach: items" class="col">
    <ul data-bind="sortable: { template: 'widgetTmpl', data: columns, afterMove: $root.widgetData }"></ul>
  </div>
</div>

我的第一个问题,我意识到我当时并没有考虑,所以跳过那个。

问题 #2:我现在如何将这些小部件绑定到我在表单中选择的 col? 我会这样做吗?

<ul data-bind="sortable: { template: 'widgetTmpl', data: entryColumn, afterMove: $root.widgetData }"></ul>

还是我走远了? :)

【问题讨论】:

    标签: javascript jquery mvvm knockout.js knockout-sortable


    【解决方案1】:

    我会将列中的项目集合作为一种类型,如下所示:

    var Column = function(header) {
        this.header = ko.observable(header);
        this.items = ko.observableArray([]);
    };
    

    诀窍是将列 select 直接绑定到视图模型上的列列表:

    <select data-bind="options: columns, optionsText: 'header', value: entryColumn"
    

    这里发生的情况是,下拉列表选择的实际column 对象将存储在entryColumn 属性中。稍后我们可以将项目直接放入其items 列表中,因为我们将引用它。这也允许我们在不改变逻辑的情况下支持任意数量的列。

    添加代码将保持简单:

    self.columns = ko.observableArray(columns);
    
    self.entryName = ko.observable('');
    self.entryType = ko.observable('');
    self.entryColumn = ko.observable('');
    self.types = ko.observableArray(['Small', 'Medium', 'Large']);
    
    self.addWidget = function() {
            var widget = new Widget(self.entryName(), self.entryType());
            //Here is where we can directly add to the selected columns item list
            self.entryColumn().items.push(widget);
            self.resetForm();
        };
    

    这里是 the fiddle 演示这些。


    后续问题

    您已经接近了,但数据是 items 而不是 EntryColumn

    <div data-bind="foreach: columns">
        <div data-bind="sortable: { template: 'widgetTmpl', data: items}" class="column">        
        </div>
    </div>
    
    <script type="text/html" id="widgetTmpl">
        <p data-bind="text: name() + ' - ' + type()"></p>
    </script>
    

    这里是updated fiddle

    【讨论】:

    • 非常感谢 Tyrsius,成功了!我有几个后续问题,但是与 foreach 循环和一般视图有关,现在用后续问题编辑主要帖子。然而,这回答了手头的问题,所以我将其标记为已接受的答案。再次感谢!
    • 我们开始了!非常感谢您的帮助,这在我的代码中确实打扫了房子。希望一旦 KnockoutJS 变得艰难,我会再见到你!干杯!
    • @KasperLewau 我添加了一些关于绑定中发生的事情的更多细节。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    相关资源
    最近更新 更多