我无疑在这里遗漏了一些明显的东西。这是我创建的第一个前端应用程序。
我想要一个客户端选择框,当选择一个选项时,将更新实体上的单独属性。更改选择框时的含义,调用一个函数,然后适当地更新另一个属性。我遇到的问题是,当在客户端创建实体时,选择框不会呈现。
在图片中:
Step One:页面已加载。该实体不存在子项:
Step Two:单击“添加子项”,并创建子实体。如您所见,选择框没有选项。使用Chrome Knockout插件,我可以看到包含应该呈现的选项的属性是正确的。
Step Three:点击“保存”,然后刷新页面。选择框正确呈现,但重要的是填充此选择框的值与第二步相同(通过knockout chrome plugin验证)。
HTML:
<section data-bind="with: parent">
<div data-bind="foreach: children">
<select name="propertyOne"
data-bind="options: propertyOneOptions, value: propertyOne, optionsText: 'description', optionsCaption: 'Select a Property'">
</select>
<br />
</div>
<button data-bind="click: $root.addChild">Add Child</button>
</section>
<button data-bind="click: save">Save</button>
查看型号:
如您所见,在initVm方法和addChild方法中,我填充了child.propertyOneOptions。
app.viewModel = (function (logger, dataservice) {
var parent = ko.observable(null);
var propertyOneValues = ko.observableArray([]);
var vm = {
addChild: addChild,
parent: parent,
save: save,
};
initVm();
return vm;
function initVm() {
propertyOneValues.push({
key: 'key 1',
description: 'value 1'
});
propertyOneValues.push({
key: 'key 2',
description: 'value 2'
});
dataservice.getAllParents()
.then(function (data) {
console.log('Number of parents = ' + data.results.length);
if (data.results.length > 0) {
parent(data.results[0]);
} else {
parent(dataservice.createParent());
dataservice.saveChanges().fail(queryFailed);
}
ko.utils.arrayForEach(parent().children(), function (child) {
console.log('Populating Child ' + child.propertyOneOptions().length);
ko.utils.arrayForEach(propertyOneValues(), function (value) {
child.propertyOneOptions.push(value);
});
console.log('Populated Child ' + child.propertyOneOptions().length);
});
}).fail(queryFailed);
}
function queryFailed(error) {
console.log('Query failed: ' + error.message);
}
function save() {
dataservice.saveChanges().fail(queryFailed);
}
function addChild() {
var child = dataservice.createChild(parent);
console.log('Creating Child ' + child.propertyOneOptions().length);
ko.utils.arrayForEach(propertyOneValues(), function (value) {
child.propertyOneOptions.push(value);
});
console.log('Populated Child ' + child.propertyOneOptions().length);
}
})(app.logger, app.dataservice);
// Bind viewModel to view in index.html
ko.applyBindings(app.viewModel);
儿童初始化器:
propertyOne和propertyOneOptions正在创建一个breeze实体初始化器:
function childInitializer(child) {
child.propertyOne = ko.observable();
child.propertyOneOptions = ko.observableArray();
}
数据模型:
public class Parent
{
public Parent()
{
Children = new List<Child>();
}
[Key]
public int Id { get; set; }
public String OtherProperty { get; set; }
public IList<Child> Children { get; set; }
}
public class Child
{
[Key]
public int Id { get; set; }
public int ParentId { get; set; }
[ForeignKey("ParentId")]
public Parent Parent { get; set; }
}
更新1
在阅读this表现后,我添加了:
parent().children.valueHasMutated();
到addChild方法的结尾并且事情有所改进,那就是一个子选择框确实渲染,但正确的子项下面有一个幻影子:Updated Step Two
答案 0 :(得分:0)
您永远不必调用valueHasMutated。我从未遇到过实际需要的情况。问题很可能是在通知已添加实体的Knockout之前没有加载所有属性,并且当它尝试绑定绑定时正在中断。
function addChild() {
// Don't pass a parent into createChild yet
var child = dataservice.createChild();
// After the entity is created, then assign the parent property
child().parent(parent());
console.log('Creating Child ' + child.propertyOneOptions().length);
ko.utils.arrayForEach(propertyOneValues(), function (value) {
child.propertyOneOptions.push(value);
});
console.log('Populated Child ' + child.propertyOneOptions().length);
}
这对我来说总是有用的。