ここで明らかな何かが間違いなく欠けています。これは私が作成した最初のフロント エンド アプリケーションです。
オプションが選択されると、エンティティの別のプロパティが更新されるクライアント側の選択ボックスが必要です。つまり、選択ボックスが変更されると、関数が呼び出され、他のプロパティが適切に更新されます。私が抱えている問題は、エンティティがクライアント側で作成されると、選択ボックスがレンダリングされないことです。
写真で:
ステップ 1 : ページが読み込まれます。エンティティは子なしで存在します:
ステップ 2 : Add Child をクリックすると、子エンティティが作成されます。ご覧のとおり、選択ボックスにはオプションがありません。Chrome Knockout プラグインを使用すると、レンダリングされるはずのオプションを含むプロパティが正しいことがわかります。
ステップ 3 : [保存] をクリックして、ページを更新します。選択ボックスは正しくレンダリングされますが、重要なことに、この選択ボックスに入力される値はステップ 2 と同じです (ノックアウト chrome プラグインで確認)。
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 は簡単なエンティティ初期化子を作成しています:
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
パフォーマンスについてこれを読んだ後、次のように追加しました。
parent().children.valueHasMutated();
addChild メソッドの最後までと、改善されました。つまり、子の選択ボックスはレンダリングされますが、正しい子の下にファントムの子があります:更新されたステップ 2