基本剔除 child 更改保存 parent
Basic knockout Save parent on child changes
我有一个基本的淘汰赛问题:
我有一个 objects 的列表,格式如下:
[{ 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>
我该如何进行?提前致谢。
在我们开始之前:你的代码片段中有很多语法错误,还有很多根本没有用到的东西。我冒昧地移动了一些东西并删除了一些代码.
您想为颜色字符串创建双向数据绑定,但您正在使用字符串和数组渲染普通对象;这些将不支持通过 value
数据绑定进行更新。
正在创建第二层视图模型
做事的"knockout way"就是为每一个要渲染和交互的item创建一个viewmodel。因此,对于您的情况,我创建了一个 ColorItem
视图模型。目前,该项目仅包含一个 name
和一个 values
列表(颜色的字符串名称)。为了可读性,我将字符串包装在一个普通对象中,这样我们就可以通过键入 value: value
进行数据绑定,而不必使用 $data
.
存储选择并绑定到它
现在有了 ColorItem
的列表,我们可以在我们的 selectedColor
可观察对象中放置一个 ColorItem
实例;请注意,您不需要选择 属性 来存储。您可以存储整个项目!
<table>
现在使用 with: selectedColor
绑定绑定到 selectedColor
。这意味着 table 的上下文是一个具有 name
和 values
属性.
的对象
正在订阅更改;存储状态
最后,为了能够对 any 颜色项目的 any 变化做出反应,我们计算了一个 "state":反映所做的所有更改的普通 javascript 对象。 (请注意,如果您打算创建一个非常大的应用程序,这可能太昂贵了)。
对于这个例子,状态只不过是所有可观察属性的展开版本。通过获取 ko.computed
或 ko.pureComputed
中的可观察值的值,knockout 会自动为您创建对任何未来更改的订阅。
我对下面示例中的一些代码进行了注释。让我知道您是否理解所有这些内容以及它是否回答了您所有的问题。
注意:部分代码假定您需要添加其他功能,例如更改名称和添加更多颜色。如果不需要,可以用常规值替换某些 observable
和 observableArray
属性。您也可以删除 "interim state" 并只输出您想要的对象格式。
// 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>
我有一个基本的淘汰赛问题: 我有一个 objects 的列表,格式如下:
[{ 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>
我该如何进行?提前致谢。
在我们开始之前:你的代码片段中有很多语法错误,还有很多根本没有用到的东西。我冒昧地移动了一些东西并删除了一些代码.
您想为颜色字符串创建双向数据绑定,但您正在使用字符串和数组渲染普通对象;这些将不支持通过 value
数据绑定进行更新。
正在创建第二层视图模型
做事的"knockout way"就是为每一个要渲染和交互的item创建一个viewmodel。因此,对于您的情况,我创建了一个 ColorItem
视图模型。目前,该项目仅包含一个 name
和一个 values
列表(颜色的字符串名称)。为了可读性,我将字符串包装在一个普通对象中,这样我们就可以通过键入 value: value
进行数据绑定,而不必使用 $data
.
存储选择并绑定到它
现在有了 ColorItem
的列表,我们可以在我们的 selectedColor
可观察对象中放置一个 ColorItem
实例;请注意,您不需要选择 属性 来存储。您可以存储整个项目!
<table>
现在使用 with: selectedColor
绑定绑定到 selectedColor
。这意味着 table 的上下文是一个具有 name
和 values
属性.
正在订阅更改;存储状态
最后,为了能够对 any 颜色项目的 any 变化做出反应,我们计算了一个 "state":反映所做的所有更改的普通 javascript 对象。 (请注意,如果您打算创建一个非常大的应用程序,这可能太昂贵了)。
对于这个例子,状态只不过是所有可观察属性的展开版本。通过获取 ko.computed
或 ko.pureComputed
中的可观察值的值,knockout 会自动为您创建对任何未来更改的订阅。
我对下面示例中的一些代码进行了注释。让我知道您是否理解所有这些内容以及它是否回答了您所有的问题。
注意:部分代码假定您需要添加其他功能,例如更改名称和添加更多颜色。如果不需要,可以用常规值替换某些 observable
和 observableArray
属性。您也可以删除 "interim state" 并只输出您想要的对象格式。
// 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>