我想要达到的目标:
具有一个文本输入字段(名称),两个选择字段以及某些选项(类型和列)的表单,以及一个提交按钮,该按钮创建一个小部件,其标题设置为Name,数据类型设置为Type和Column-是其位置这一页。

在这种情况下,Type在 View 中定义了几个不同的选项,它的工作方式很花哨,因此暂时不介绍如何工作。

到目前为止,我有一个包含三列的页面,每列都是自己的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,有效!

但是,这只会将新的窗口小部件输出到第一个col(col0)中,不会考虑列选择字段的值,也不会将新的窗口小部件移到正确的列中。经过反复尝试后,我遇到的错误归结为:

1)“无法调用未定义的方法取消转移”

2)“未捕获的TypeError:对象函数observable()....没有方法'unshift'

因此,到目前为止,代码看起来像上面的示例,这绝对不是理想的选择,但是将不同的列与可 knockout 可排序连接在一起,如果必须放弃此功能,这并不是什么大问题。用户仍然可以将小部件从col0移动到col2,反之亦然。

如果任何人有资源可以向我指出正确的方向,或者可以回答他们的问题,请随时分享!

祝一切顺利,Kas。

编辑:Tyrsius的后续问题

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

在我之前的代码中, View 是这样的:
<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:我现在如何将这些小部件绑定(bind)到表单中选择的col?
我会这样做吗?
<ul data-bind="sortable: { template: 'widgetTmpl', data: entryColumn, afterMove: $root.widgetData }"></ul>

还是我要离开? :)

最佳答案

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

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

诀窍是将select列直接绑定(bind)到 View 模型上的列列表:
<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

关于javascript - 将observableArray作为函数参数传递,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15392445/

10-11 19:13
查看更多