我想要实现的目标: 带有一个文本输入字段(Name)的表单,带有一些选项的两个选择字段(Type& Column),带有一个提交按钮,创建一个Widget,其标题设置为Name,数据类型设置为Type和Column - 是它的位置在页面中。
在这种情况下,类型在视图中定义了几个不同的选项,它只是花花公子,所以我现在不会讨论我是如何工作的。
截至目前,我有一个包含三列的页面,每个列都是自己的observableArray - 就像这样:
self.col0 = ko.observableArray([]);
self.col0.id = 'col0'
col1和col2也是如此。我的目标是让select字段指向这些数组。至少这是我认为我需要做的事情。
我有一个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函数的click处理程序 - 就像这样:
a.btn.create-widget data-bind="click: function(){ createWidget(col0); }"
Shazam,它有效!
但是,这只会将新的Widget输出到第一个col(col0),它不会考虑列选择字段的值,并将新窗口小部件卸载到正确的列中。经过多次试验和错误后我得到的错误几乎归结为:
1)“无法调用未定义的未定义方法”
2)“Uncaught TypeError:Object function observable()....没有方法'unshift'
所以现在代码看起来像上面的例子,它不是理想的,但是不同的列与knockout-sortable连接,如果这个功能必须废弃,这不是一个大问题。用户仍然可以将小部件从col0移动到col2,反之亦然。
如果有人有资源可以指引我朝着正确的方向前进,或者回答他们的问题 - 请随时分享!
一切顺利,卡斯。
编辑:Tyrsius的后续问题
使用您提供的代码,我现在在选择框中有三列工作,但是当我将Widgets输出到视图中时,我正在努力。
使用我之前的代码,这就是视图的样子:
<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>
还是我离开了? :)
答案 0 :(得分:3)
我会将列上的项目集合作为类型保存,如下所示:
var Column = function(header) {
this.header = ko.observable(header);
this.items = ko.observableArray([]);
};
诀窍是将列select
直接绑定到viewmodel上的列列表中:
<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>