从弹出窗口向可观察数组添加项

时间:2013-07-10 17:18:00

标签: knockout.js

我一直在玩Knockout而且我无法理解如何处理这个场景。

基本上我有一份员工清单,您可以从选择控件中选择该员工的职位。我已经使用jquery创建了一个小弹出窗口,以便用户可以添加一个新位置。然后,这将更新基础页面中的选择。我可以调用viewmodel的addPosition方法,它添加了一个带有一些测试数据的新位置,但是我无法理解如何从弹出文本字段中的值填充它。

这是我的小提琴

http://jsfiddle.net/ricobano/HA5uz/3/

<div id="employeeWrapper">
    <div data-bind="foreach: employees">
        <div>
            <label>Full Name</label>
            <input type="text" data-bind="value: fullName" />
            <label>Position</label>
            <select id="slTest" data-bind="options: $root.Positions, value:position, optionsText:'name'"></select>
            <label>Salary:</label><span data-bind="text: position().formatted"></span>
        </div>
    </div>
    <button id="button"  data-bind="click: addEmployee">Add Employee</button>
    <button id="AddPosition" data-bind="click: open">Add Position</button>
</div>

<div data-bind="dialog: {autoOpen: false, title: 'Dialog test' },  dialogVisible: isOpen">
    <div>
        <label>Name:</label><input type="text"/>
    </div>
    <div>
        <label>salary:</label><input type="text"/>
    </div>
    <button data-bind="click: addPosition">Add</button>
 </div>

继承我的viewmodel

ko.bindingHandlers.dialog = {
    init:function(element, valueAccessor, allBindingsAccessor){
        var options = ko.utils.unwrapObservable(valueAccessor()) || {};
        setTimeout(function() { 
                options.close = function() {
                    allBindingsAccessor().dialogVisible(false);                        
                };

                $(element).dialog(options);     
            }, 0); 
    },
     update: function(element, valueAccessor, allBindingsAccessor) {
            var shouldBeOpen = ko.utils.unwrapObservable(allBindingsAccessor().dialogVisible),
                $el = $(element),
                dialog = $el.data("uiDialog") || $el.data("dialog")

            //don't call open/close before initilization
            if (dialog) {
                $el.dialog(shouldBeOpen ? "open" : "close");
            }  
        }
};

function Employee(fullname, position) {
    var self = this;
    self.fullName = ko.observable(fullname);
    self.position = ko.observable(position);
};

function Position(data) {
    var self = this;
    self.id = ko.observable(data.id);
    self.name = ko.observable(data.name);
    self.salary = ko.observable(data.salary);

    self.formatted = ko.computed(function(){
        return "£" + self.salary();
    });
};

function EmployeeVM() {
    var self = this;
    self.employees = ko.observableArray();
    self.Positions = ko.observableArray([]);
    self.isOpen = ko.observable(false);

    var PositionsJSON = {
        json: $.toJSON([{
            "id": 1,
            "name" : "No position",
            "salary" : 0
        },{
            "id": 2,
            "name" : "Web Developer",
            "salary" : 15000           
        },{
            "id": 3,
            "name" : "Manager",
            "salary" : 30000           
        }])
    };

    var data = {
        json: $.toJSON([{
            "fullName": "Richard Banks",
                "position": {
                    "id": 2
            }
        }, {
            "fullName": "Dave Grohl",
                "position": {
                    "id": 3
            }
        }, {
            "fullName": "bobby rahul",
                "position": {
                    "id": 3
            }
        }])
    };

    $.when(
        $.ajax({
            url: "/echo/json/",
            data: PositionsJSON,
            type: "POST"
        }),
        $.ajax({
            url: "/echo/json/",
            data: data,
            type: "POST"
        })
    ).done(function(positionArgs, EmployeeArgs){
        var ps = $.map(positionArgs[0], function(item){
            return new Position(item);
        });

        self.Positions(ps);

        $.each(EmployeeArgs[0], function (i, item) {
            var p = ko.utils.arrayFirst(self.Positions(), function(p){
                return p.id() == item.position.id;
            });

            var e = new Employee(item.fullName, p);
            self.employees.push(e);
        });
    });

    self.addPosition = function(){
        self.Positions.push(new Position({id:"4", name:"Director", salary:"To much"}));
        self.isOpen(false);
    };

    self.addEmployee = function(){
        self.employees.push(new Employee("", self.Positions[0]));
    };

    self.open = function(){
        self.isOpen(true);
    };
}

ko.applyBindings(new EmployeeVM());

1 个答案:

答案 0 :(得分:4)

理查德,你快到了。

使用空白位置模型并将其绑定到对话框中的输入。 (每次打开对话框时,请务必清空该模型的值。)

function EmployeeVM() {
    var self = this;
    ...
    self.dialogPosition = new Position({id:'',name:'',salary:''})
};

(绑定......)

<div data-bind="dialog: {autoOpen: false, title: 'Dialog test' },  dialogVisible: isOpen">
    <!-- ko with: dialogPosition -->
    <div>
        <label>Name:</label><input type="text" data-bind="value:name"/>
    </div>
    <div>
        <label>salary:</label><input type="text" data-bind="value:salary"/>
    </div>
    <!-- /ko -->
    <button data-bind="click: addPosition">Add</button>
 </div>

当对话框以“添加”按钮关闭时,复制该位置对象并将 copy 推送到self.Positions()可观察数组。这将自动更新您的选择。

self.addPosition = function(){
    var newPosition = new Position({id:'',name:self.dialogPosition.name(),salary:self.dialogPosition.salary()});
    self.Positions.push(newPosition);
    self.isOpen(false);
}

我已经更新了你的小提琴(没有清除对话框位)http://jsfiddle.net/HA5uz/5/

希望它有所帮助!