我有一个基本的淘汰赛问题: 我有这种格式的对象列表:
[{ Name: "Colors1", Values: ["red", "yellow", "blue"] },
{ Name: "Colors2", Values: ["red", "pink", "blue"] },
{ Name: "Colors3", Values: ["black", "white", "green"] }]);
我想要一个带有颜色名称的下拉列表。在选择更改时,值中的颜色应显示在文本框中。 在文本框中更改颜色时,应立即更新整个记录。
这就是我所拥有的:
<div>
<select data-bind="options:myitems, optionsText:'Name', optionsValue:'Name', optionsCaption:'Please select a color', value:selectedColor"></select>
<table>
<thead>
<tr>
<th>Color</th>
</tr>
</thead>
<tbody data-bind="foreach:listofColors()? ">
<tr>
<td><input data-bind="value:Value, event: { change : $parent.SaveUpdatedColors($root)?}" /></td>
</tr>
</tbody>
</table>
</div>
//----------------------------------- //
<script>
var viewModel= function() {
var self = this;
self.selectedColorChoice = ko.observable();
self.listofColors = ko.observableArray();
self.myitems = ko.observableArray(
[{ Name: "Colors1", Values: ["red", "yellow", "blue"] },
{ Name: "Colors2", Values: ["red", "pink", "blue"] },
{ Name: "Colors3", Values: ["black", "white", "green"] }]);
var getByName = function (items, name) {
return ko.utils.arrayFirst(items, function (item) {
return item.Name === name;
});
};
self.selectedColor.subscribe(function(item) //NOT WORKING
{
self.listofColors = ko.computed(function () {
var selColor = getByName(self.myitems(), self.selectedColor);
return selColor ? ko.utils.arrayMap(selColor.Values, function (item) {
return {
Name: item.Name,
Value: item.Value
};
}) : [];
}, this);
})
})
self.SaveUpdatedColors=function(fullRecord)
{ //logic to update}
}
ko.applyBindings(new viewModel());
</script>
我该怎么办?提前谢谢。
答案 0 :(得分:1)
在我们开始之前:您的代码段中存在相当多的语法错误,以及一些根本没有使用过的东西......我冒昧地移动了一些东西并删除了一些代码。
您希望为颜色字符串创建双向数据绑定,但是您要使用字符串和数组渲染普通对象;那些不会通过value
data-bind。
做事的“淘汰方式”是为要渲染和交互的每个项目创建一个视图模型。因此,对于您的情况,我创建了一个ColorItem
视图模型。此项目目前仅包含name
和values
列表(颜色的字符串名称)。为了便于阅读,我将字符串包装在普通对象中,这样我们就可以通过键入value: value
进行数据绑定,而不必使用$data
。
现在有一个ColorItem
的列表,我们可以在ColorItem
可观察的selectedColor
个实例中添加<table>
个实例。请注意,您无需选择要存储的属性。您可以存储整个项目!
selectedColor
现在使用with: selectedColor
绑定绑定到name
。这意味着表的上下文是具有values
和ko.computed
属性的对象。
最后,为了能够对任何颜色项中的任何更改做出反应,我们计算出一个“状态”:一个普通的javascript对象,它反映了所有的变化。制作。 (请注意,如果您计划创建一个非常大的应用程序,这可能太昂贵了。)
对于此示例,状态不仅仅是所有可观察属性的展开版本。通过获取<{1}}或ko.pureComputed
中的观察值,淘汰赛会自动为您预订任何未来的更改。
我评论了下面示例中的一些代码。如果您了解所有内容并且是否回答了所有问题,请告诉我。
注意:部分代码假设您要添加其他功能,例如更改名称和添加更多颜色。如果您不需要,可以使用常规值替换某些observable
和observableArray
属性。您还可以删除“临时状态”,仅输出所需的对象格式。
// Our starting data
var colors = [{
Name: "Colors1",
Values: ["red", "yellow", "blue"]
}, {
Name: "Colors2",
Values: ["red", "pink", "blue"]
}, {
Name: "Colors3",
Values: ["black", "white", "green"]
}];
var ViewModel = function() {
var self = this;
// Create ColorItem viewmodels
self.listOfColors = ko.observableArray(
colors.map(ColorItem.createFromData));
self.selectedColor = ko.observable();
// Computed state, holds name of current selection and list of items
self.colorState = ko.pureComputed(function() {
return {
selectedColorName: self.selectedColor() ? self.selectedColor().name() : null,
colorStates: self.listOfColors().map(function(colorItem) {
return colorItem.state();
})
};
});
// By subscribing to the computed state, we can trigger any other methods
self.colorState.subscribe(function(newState) {
// If you want to save to server, you'll need to rate limit updates
// and abort previous posts
// To convert back to your original format:
console.log(JSON.stringify(
newState.colorStates.map(function(itemState) {
return { Name: itemState.name, Values: itemState.values };
}))
);
});
};
var ColorItem = function(name, values) {
this.name = ko.observable(name);
this.values = ko.observableArray(values.map(function(str) {
return {
// By wrapping the string in an observable, we can bind
// the input's value to it
value: ko.observable(str)
};
}));
// Color items hold their own state: name and a list of strings
this.state = ko.pureComputed(function() {
return {
name: this.name(),
values: this.values().map(function(valueObj) {
return valueObj.value();
})
};
}, this);
};
// A helper function to transform a {Name, Values} object in to a viewmodel
ColorItem.createFromData = function(data) {
return new ColorItem(data.Name, data.Values);
};
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div>
<select data-bind="options:listOfColors,
optionsText:'name',
optionsCaption:'Please select a color',
value:selectedColor"></select>
<table data-bind="with: selectedColor">
<thead>
<tr>
<th>Color</th>
</tr>
</thead>
<tbody data-bind="foreach:values">
<tr>
<td>
<input data-bind="textInput: value" />
</td>
</tr>
</tbody>
</table>
</div>