Knockout嵌套foreach添加和删除不工作

时间:2015-04-13 02:26:06

标签: javascript html knockout.js

我在嵌套的foreach中添加和删除时遇到了麻烦。在这个例子中,我们有一个房子,有很多房间。每间客房均配有许多家具。到目前为止,使用此代码,我可以正确显示数据并可以添加和删除Rooms,但我无法添加或删除Furniture。

HTML

//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> 

的JavaScript

var HouseModel = function(rooms) {

    var self = this;
    self.rooms = ko.observableArray(rooms);

    // Not sure what to put here for Furniture because each room array item has an array of many furnitures

    // ROOM MANAGEMENT ==========================
    self.addRoom = function() {
        self.rooms.push({
            name:"",
            furnitures[]: ""
        });
    };

    self.removeRoom = function(room) {
        self.rooms.remove(room);
    };

            // FURNITURE MANAGEMENT ==========================
            // Not sure where this goes
            self.addFurniture = function() {
                self.furnitures.push({
                    name: ""
                });
            };

            self.removeFurniture = function(furniture) {
                self.furnitures.remove(furniture);
            };
};

var viewModel = new HouseModel(rooms); // rooms are the pre-existing rooms and their furniture, in JSON format
ko.applyBindings(viewModel);

这方面的主要问题可能与按钮的数据绑定的上下文以及模型的编码方式有关。有些东西丢失或错误。

我们对此表示赞赏。

更新 这是问题的一个小问题: http://jsfiddle.net/zhLf1n61/

资源:

2 个答案:

答案 0 :(得分:1)

更新了javascript ...

主要入口点是HouseModel ...房屋有房间(以及删除添加它们的方法)和房间有家具(有添加和删除它们的方法)。这完全取决于封装和范围。

在这里小提琴:http://jsfiddle.net/zqwom7kd/

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));

<强> 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>

答案 1 :(得分:0)

这是一个值得一去的地方。正如@Nathan Fisher所提到的,创建Room甚至可能是Furniture类是有意义的。

HTML

<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>   

JS

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);
    };
};