在内联编辑模型属性时通过ajax更新

时间:2013-11-22 16:28:54

标签: knockout.js

当通过内联编辑更改挖空模型字段值时,如何调用挖空模型Update(fieldName, newValue)(通过ajax调用某些api并更新fieldName = newValue)?

我正在使用以下内联编辑功能 Knockout Inline Edit Binding

ko.bindingHandlers.hidden = {
    update: function(element, valueAccessor) {
        ko.bindingHandlers.visible.update(element, function() { return !ko.utils.unwrapObservable(valueAccessor()); });
    }        
};

ko.bindingHandlers.clickToEdit = {
    init: function(element, valueAccessor) {
        var observable = valueAccessor(),
            link = document.createElement("a"),
            input = document.createElement("input");

        element.appendChild(link);
        element.appendChild(input);

        observable.editing = ko.observable(false);

        ko.applyBindingsToNode(link, {
            text: observable,
            hidden: observable.editing,
            click: observable.editing.bind(null, true)
        });

        ko.applyBindingsToNode(input, {
            value: observable,
            visible: observable.editing,
            hasfocus: observable.editing
        });
    }
};

clickToEdit自定义绑定允许元素在编辑时成为输入框。

现在,我需要实现自动保存。 这意味着要为刚刚编辑过的值(焦点丢失或类似时)调用Update(fieldName,newValue)。

我是淘汰赛的新手,所以不明白如何实现这个的逻辑。

编辑:我设法做了一些事,但我知道我的解决方案很糟糕。

我修改了bindingHandlers(在这里找到:http://jsfiddle.net/rniemeyer/8D5aj/) 并添加了调用数据保存的focusout事件。

  1. 不幸的是,当页面加载时,每个字段都会调用它,我不需要这个。
  2. 而且我也不知道如何在此活动中获得可观察的字段名称和值
  3. 最后我只能在字段真正改变时才能保存(现在这不是很重要)
  4. 脚本

    ko.bindingHandlers.clickToEdit = {
        init: function (element, valueAccessor) {
            var observable = valueAccessor(),
                link = document.createElement("a"),
                input = document.createElement("input");
    
            element.appendChild(link);
            element.appendChild(input);
    
            observable.editing = ko.observable(false);
    
            ko.applyBindingsToNode(link, {
                text: observable,
                hidden: observable.editing,
                click: observable.editing.bind(null, true)
            });
    
            ko.applyBindingsToNode(input, {
                value: observable,
                visible: observable.editing,
                hasfocus: observable.editing,
                event: {
                    keyup: function (data, event) {
                        //if user hits enter, set editing to false, which makes field lose focus
                        if (event.keyCode === 13) {
                            observable.editing(false);
                            return false;
                        }
                            //if user hits escape, push the current observable value back to the field, then set editing to false
                        else if (event.keyCode === 27) {
                            observable.valueHasMutated();
                            observable.editing(false);
                            return false;
                        }
    
                    },
                    focusout: function (data, event) {
    
                        // this is for test as I do not know how to get fieldname and value
                        var d = {
                            Field: "CompanyName",
                            Value: "Value"
                        };
                        var json = JSON.stringify(d)
    
    
                        $.ajax({
                            url: "/api/MyObject/PutValue/5",
                            contentType: "text/json",
                            dataType: "json",
                            type: "PUT",
                            data: json,
                            success: function(data) {
                                //
                            }
                        });
                    }
                }
            });
        }
    
        //update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
    
        //}
    
    };
    

2 个答案:

答案 0 :(得分:2)

如果您愿意在解决方案中使用多个绑定,为什么不尝试在knockoutjs文档页面中记录为Example 2: Click-to-edit的简单绑定?

标记

<p>
    Name: <b data-bind="visible: !editing(), 
                        text: name, 
                        click: edit">&nbsp;</b>    
    <input data-bind="visible: editing, 
                      value: name, 
                      hasFocus: editing, 
                      event: { blur: myblurFunction }" />
</p>
<p><em>Click the name to edit it; click elsewhere to apply changes.</em></p>

脚本

function PersonViewModel(name) {
    var self = this;
    self.name = ko.observable(name);
    self.editing = ko.observable(false);
    self.edit = function () {
        this.editing(true);
    }
    this.myblurFunction = function() {
        var newName = self.name();
        alert("Houston! We have lost focus on " + newName); 
        // ajax call here.   
    }
}

ko.applyBindings(new PersonViewModel("Bert Bertington"));

小提琴:http://jsfiddle.net/codovations/Q66bQ/

答案 1 :(得分:2)

我认为保存到数据库的最佳方法是在视图模型中订阅observable并在那里触发AJAX调用。

因此,在您的视图模型中,它看起来像:

myObservable.subscribe(function(newValue) {
    //call your update here with the field name and newValue
});

您甚至可以添加一个简单的扩展程序:

ko.subscribable.fn.withUpdater = function(prop, handler) {
      this.subscribe(handler.bind(this, prop));

      //support chaining 
      return this;

};

现在您可以在视图模型中使用它,如:

this.firstName = ko.observable("Bob").withUpdater("firstName", yourUpdateFunction);

以下是一个示例:http://jsfiddle.net/rniemeyer/dy2f5/