我正在尝试将新对象添加到我的knockout mapping plugin dowloaded viewmodel中,如下所示:
<script type="text/javascript">
var myViewModel = {};
var Fighter = function (data) {
var self = this;
self.Name = ko.observable(data.Name);
self.Country = ko.observable(data.Country);
self.TopSpeed = ko.observable(data.TopSpeed);
};
var WarCraft = function (data) {
var self = this;
self.fighter = ko.observable(data.fighter);
};
var dataMappingOptions = {
key: function (data) {
return data.id;
},
create: function (options) {
if (data.id == 1)
return new Fighter(options.data);
else
if (data.id == 2)
return new WarCraft(options.data);
}
};
$.getJSON("/Home/GetServerData", function (model) {
ko.mapping.fromJS(model, dataMappingOptions, myViewModel);
ko.applyBindings(myViewModel);
}).error(function () { alert("Oops!") }).success(function () { alert("Yeah!") });
myViewModel.AddToData = function () {
var newFighter = new Fighter(
{
id : 1,
Name: myViewModel.warCraft.fighter.Name(),
Country: myViewModel.warCraft.fighter.Country(),
TopSpeed: myViewModel.warCraft.fighter.TopSpeed()
});
var newWarCraft = new WarCraft({ id: 2, fighter: newFighter });
myViewModel.WW2Machines.push(newWarCraft);
}.bind(myViewModel);
</script>
服务器端模型:
DataModel model = new DataModel();
model.warCraft = new WarCraft();
model.warCraft.fighter = new Fighter();
model.warCraft.fighter.Name = "Spitfire";
model.WW2Machines = new List<WarCraft>();
WarCraft w1 = new WarCraft();
w1.fighter = new Fighter() { Name = "Spitfire" };
model.WW2Machines.Add(w1);
WarCraft w2 = new WarCraft();
w2.fighter = new Fighter() { Name = "Hurricane" };
model.WW2Machines.Add(w2);
WarCraft w3 = new WarCraft();
w3.fighter = new Fighter() { Name = "Tomcat" };
model.WW2Machines.Add(w3);
... Ajax调用调用的方法,它初始化并发送数据:
DataModel model = new DataModel();
model.warCraft = new WarCraft();
model.warCraft.fighter = new Fighter();
model.warCraft.fighter.Name = "Spitfire";
model.WW2Machines = new List<WarCraft>();
WarCraft w1 = new WarCraft();
w1.fighter = new Fighter() { Name = "Spitfire" };
model.WW2Machines.Add(w1);
WarCraft w2 = new WarCraft();
w2.fighter = new Fighter() { Name = "Hurricane" };
model.WW2Machines.Add(w2);
WarCraft w3 = new WarCraft();
w3.fighter = new Fighter() { Name = "Tomcat" };
model.WW2Machines.Add(w3);
return Json(model, JsonRequestBehavior.AllowGet);
。 。 。和我的HTML:
<div id="show" data-bind="visible: WW2Machines().length>0">
<h2>Information Display:</h2>
NewNumber : <span data-bind="text: WW2Machines().length"></span>
<ul data-bind="foreach: WW2Machines">
<li>
Name: <span data-bind="text: fighter.Name"></span>
<br> </br>
</li>
</ul>
</div>
<div id="theForm">
@using (Html.BeginForm())
{
<legend WW2 Fighter Planes: >
<fieldset>
Name:
<br> </br>
<select data-bind="value: warCraft.fighter.Name, optionsCaption: 'Please Select . . '">
<option>Mosquito</option>
<option>Mustang</option>
<option>Messerschmidt 109</option>
</select>
<br> </br>
<span data-bind="text: warCraft.fighter.Name"></span>
<br> </br>
Country:
<br> </br>
<select data-bind="value: warCraft.fighter.Country, optionsCaption: 'Please Select . . '">
<option>England</option>
<option>USA</option>
<option>Germany</option>
</select>
<br> </br>
<span data-bind="text: warCraft.fighter.Country"></span>
<br> </br>
Top Speed:
<br> </br>
<select data-bind="value: warCraft.fighter.TopSpeed, optionsCaption: 'Please Select . . '">
<option>390 km/h</option>
<option>275 km/h</option>
<option>250 km/h</option>
</select>
<br> </br>
<span data-bind="text: warCraft.fighter.TopSpeed"></span>
<input type="button" data-bind="click: AddToData">Add</input>
</fieldset>
</legend>
}
问题是我的“添加”按钮被触发并向显示区域添加行,除非它们是空的。在Firefox的调试器控制台中,我看到我可以引用从服务器发送的行,以及添加按钮(正确包含数据)添加的行,但有一个令人费解的区别: 我使用以下语法访问现有行:
myViewModel.WW2Machines()[0] .fighter.Name()
。 。 。以及我用这种语法添加的行:
myViewModel.WW2Machines()[3] .fighter()。名称()
。 。 。并且为各个下标在彼此之间交换语法会引发错误。这可能是为什么我的行被添加为空白的线索,但我不知道为什么?有人可以帮忙吗?
答案 0 :(得分:0)
至少有一些问题 - 以及你在底部遇到的令人费解的差异的解释 - 是你之后添加的行使WarCraft.fighter
成为一个可观察的,映射插件不是这样做。
所以你可以交换一下:
var WarCraft = function (data) {
var self = this;
self.fighter = ko.observable(data.fighter);
};
这个
var WarCraft = function (data) {
var self = this;
self.fighter = data.fighter;
};
您应该能够以相同的方式访问映射数据和添加数据:
myViewModel.WW2Machines()[0].fighter.Name()
答案 1 :(得分:0)
Adrien,您是否可以解释为什么映射插件不会使WarCraft.fighter可观察到?我认为使用插件映射的所有对象和子属性都默认为observable。谢谢,