Javascript 敲除嵌套的foreach添加和删除不起作用
在嵌套的foreach中添加和删除时遇到问题。在这个例子中,我们有一个有很多房间的房子。每个房间都有许多家具。到目前为止,使用这段代码,我可以正确显示数据,可以添加和删除房间,但无法添加或删除家具 HTMLJavascript 敲除嵌套的foreach添加和删除不起作用,javascript,html,knockout.js,Javascript,Html,Knockout.js,在嵌套的foreach中添加和删除时遇到问题。在这个例子中,我们有一个有很多房间的房子。每个房间都有许多家具。到目前为止,使用这段代码,我可以正确显示数据,可以添加和删除房间,但无法添加或删除家具 HTML //Other House fields work as expected above this section <div data-bind='foreach: rooms'> <button type="button" data-bind='visible:
//Other House fields work as expected above this section
<div data-bind='foreach: rooms'>
<button type="button" data-bind='visible: $root.rooms().length > 1, click: $root.removeRoom'> Remove Room </button>
<p> Room Name</p>
<input type="text" data-bind="value: name"></input>
//with: appears to work the same as a foreach -- neither seem to work
<div data-bind="with: furnitures">
<button type="button" data-bind='click: $root.rooms().furnitures().removeFurniture'> Remove Furniture </button>
<p> Furniture Name</p>
<input type="text" data-bind="value: name"></input>
</div>
<button type="button" data-bind='click: $root.rooms().furnitures().addFurniture'> Add Furniture </button>
</div>
<button type="button" data-bind='click: $root.addRoom'> Add Room </button>
这方面的主要问题可能与按钮的数据绑定上下文以及模型的编码方式有关。有东西不见了或出了问题
思想是值得赞赏的
更新
这是一个棘手的问题:
资源:
- (此示例不同,因为它没有嵌套的视图模型)
- (我发现这很难适用于我的情况)
- 这里是一个开始。正如@Nathan Fisher所提到的,创建一个
房间
,甚至可能创建一个家具
类是有意义的
HTML
更新的javascript
主要的切入点是房屋模型。。。房屋有房间(以及删除和添加房间的方法),房间有家具(以及添加和删除房间的方法)。这都是关于封装和范围的
在这里拉小提琴:
HTML
<h2>House Components</h2>
<div id='roomsList'>
<table class='roomsEditor'>
<tr>
<th>Room Name</th>
<th>Furnitures</th>
</tr>
<tbody data-bind="foreach: rooms">
<tr class="well">
<td valign="top">
<input type="text" data-bind='value: name' />
<div> <button class="btn btn-danger" data-bind='click: $root.rooms.removeRoom'>Remove Room</button>
</div>
</td>
<td>
<table>
<tbody data-bind="foreach: furnitures">
<tr>
<td>
<input type="text" data-bind='value: name' />
</td>
<td>
<input type="text" data-bind='value: size' />
</td>
<td>
<button class="btn btn-danger" data-bind='click: $parent.removeFurniture'>Delete Furniture</button>
</td>
</tr>
</tbody>
</table>
<button class="btn btn-success" data-bind='click: addFurniture'>Add Furniture</button>
</td>
</tr>
</tbody>
</table>
</div>
<p>
<button class="btn btn-success" data-bind='click: $root.rooms.addRoom'>Add Room</button>
<button data-bind='click: save, enable: rooms().length > 0'>Save to JSON</button>
</p>
<textarea data-bind='value: lastSavedJson' rows='5' cols='60' disabled='disabled'></textarea>
内部组件
房间名称
家具
搬家
删除家具
添加家具
增加空间
保存到JSON
您是否还可以包括房间模型,以及您想做的最有意义的附加功能。也许即使是一个jsfiddle也会是一个好主意,这就是问题所在。没有房间模型;只有一个房子模型。因此,当数据传入时,它是一个House对象,具有一个房间数组,每个房间都有一个家具数组。如果你是在暗示应该有另一个模型(房间模型),那肯定是有道理的,但我的理解是,当使用Knockout时,每页一个模型是可取的。如果我错了,请纠正我。@Max每页有多个视图模型没有什么错。尤其是当这些视图模型是模块化的可重用代码时。@Max I添加了按钮绑定示例。这会起作用,但应该注意的是,主要问题是家具需要是可观察的。这就是你最初的解决方案不起作用的原因。下面是我的意思<代码>http://jsfiddle.net/zhLf1n61/当没有房子,只有房间和家具时,它可以正常工作,但一旦我尝试将房间和家具放在房子中,我就无法再操纵furniture@Max确保将正确的参数传递到添加/删除家具。我已经更新了上面的绑定。请注意,这不使用RoomsViewModel。如果将“添加/删除家具”功能移动到房间中,则绑定需要不同。谢谢您的回答,但不幸的是,这不起作用。它显示数据,但按钮不起作用。也许按钮调用上下文是错误的?我尝试了$root.rooms().addFurniture
和$data.addFurniture
确实需要将房间和家具组合为对象,这些对象不仅具有属性,而且具有功能。你可能是对的。我在这里看到了你的另一篇帖子http://stackoverflow.com/questions/29572088/multiple-arrays-in-one-knockout-js-viewmodel/29609645#29609645
一定要试试。是的。。。非常相似。重新编辑上面的代码以显示另一种更类似的方法。我实现了建议,下面是一个fiddlehttp://jsfiddle.net/zhLf1n61/
。正如我向CrimsonChris提到的,当没有房子,只有房间和家具时,它工作得很好,但一旦我试图把房间和家具放在房子里,我就不能再操纵家具了。@布雷特格林
<button data-bind="click: addRoom"></button>
<div data-bind='foreach: rooms'>
<button data-bind="click: $parent.removeRoom"></button>
<button data-bind="click: $parent.addFurnitureToRoom"></button>
<div data-bind="foreach: furnitures">
<button data-bind="click: $parents[1].removeFurnitureFromRoom.bind($root, $data, $parent)"></button>
</div>
</div>
function HouseViewModel (rooms) {
var self = this;
this.rooms = ko.observableArray(rooms || []);
this.addRoom = function () {
self.rooms.push({
name: ko.observable(''),
furnitures: ko.observableArray(),
});
};
this.removeRoom = function (room) {
self.rooms.remove(room);
};
this.addFurnitureToRoom = function (room) {
room.furnitures.push({
name: ko.observable(''),
});
};
self.removeFurnitureFromRoom = function (furniture, room) {
room.furnitures.remove(furniture);
};
};
var initialData = [{
"name": "Living Room",
"furnitures": [{
"name": "Bookshelf",
"size": "Medium"
}]
}, {
"name": "Bedroom",
"furnitures": [{
"name": "Bed",
"size": "Large"
}, {
"name": "Night Table",
"size": "Small"
}, {
"name": "Jacuzzi",
"size": "Large"
}]
}];
var Furniture = function(data) {
var self = this;
self.name = ko.observable('');
self.size = ko.observable('');
if (typeof data !== 'undefined') {
self.name(data.name);
self.size(data.size);
}
}
var Room = function(name, furnitures) {
var self = this;
self.name = ko.observable(name);
self.furnitures = ko.observableArray([]);
if (typeof furnitures !== 'undefined') {
$.each(furnitures, function(i, el) {
self.furnitures.push(new Furniture({name: el.name, size: el.size}));
});
}
self.removeFurniture = function(furniture) {
self.furnitures.remove(furniture);
};
self.addFurniture = function() {
console.log("added");
self.furnitures.push(new Furniture({name: '', size: ''}));
};
};
var HouseModel = function (rooms) {
var self = this;
self.save = function() {
console.log("do stuff");
};
self.lastSavedJson = ko.observable('');
self.rooms = ko.observableArray([]);
if (typeof rooms !== 'undefined') {
$.each(rooms, function(i, el) {
self.rooms.push(new Room(el.name, el.furnitures));
});
}
self.addRoom = function(name) {
self.rooms.push(new Room(name));
};
self.removeRoom = function (room) {
self.rooms.remove(room);
};
};
ko.applyBindings(new HouseModel(initialData));
<h2>House Components</h2>
<div id='roomsList'>
<table class='roomsEditor'>
<tr>
<th>Room Name</th>
<th>Furnitures</th>
</tr>
<tbody data-bind="foreach: rooms">
<tr class="well">
<td valign="top">
<input type="text" data-bind='value: name' />
<div> <button class="btn btn-danger" data-bind='click: $root.rooms.removeRoom'>Remove Room</button>
</div>
</td>
<td>
<table>
<tbody data-bind="foreach: furnitures">
<tr>
<td>
<input type="text" data-bind='value: name' />
</td>
<td>
<input type="text" data-bind='value: size' />
</td>
<td>
<button class="btn btn-danger" data-bind='click: $parent.removeFurniture'>Delete Furniture</button>
</td>
</tr>
</tbody>
</table>
<button class="btn btn-success" data-bind='click: addFurniture'>Add Furniture</button>
</td>
</tr>
</tbody>
</table>
</div>
<p>
<button class="btn btn-success" data-bind='click: $root.rooms.addRoom'>Add Room</button>
<button data-bind='click: save, enable: rooms().length > 0'>Save to JSON</button>
</p>
<textarea data-bind='value: lastSavedJson' rows='5' cols='60' disabled='disabled'></textarea>