4

我去寻找一个淘汰的内联编辑绑定,但我发现的唯一一个有外部依赖项而不是 jQuery,或者使用的不仅仅是一个绑定

所以我想我会分享我想出的简单答案(当然欢迎其他答案,尤其是那些只使用淘汰赛的答案)。

4

3 回答 3

5

作为替代方案:我用于内联编辑的代码如下所示:

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

http://jsfiddle.net/rniemeyer/Rg8DM/

于 2012-11-13T14:41:04.477 回答
4

这是我的内联编辑绑定(小提琴),它依赖 jQuery 进行一些 DOM 操作。

HTML:

<p>
    Set an alarm for <span data-bind="inline: startTime"></span>
    using <span data-bind="inline: snoozeCount"></span> Snooze(s).
</p>

JS:

ko.bindingHandlers.inline= {
    init: function(element, valueAccessor) {
        var span = $(element);
        var input = $('<input />',{'type': 'text', 'style' : 'display:none'});
        span.after(input);

        ko.applyBindingsToNode(input.get(0), { value: valueAccessor()});
        ko.applyBindingsToNode(span.get(0), { text: valueAccessor()});

        span.click(function(){
            input.width(span.width());
            span.hide();
            input.show();
            input.focus();
        });

        input.blur(function() { 
            span.show();
            input.hide();
        });

        input.keypress(function(e){
            if(e.keyCode == 13){
               span.show();
               input.hide();
           }; 
        });
    }
};

由于 Dom Ready 上的宽度不可靠,因此在 click 函数中设置了宽度:一半时间它显示为 0。

我还为切换(布尔值)制作了一个,您只需单击即可切换:

ko.bindingHandlers.inlineToggle = {
    init: function(element, valueAccessor, allBindingsAccessor) {

        var displayType = allBindingsAccessor().type || "bool";
        var displayArray = [];

        if (displayType == "bool") {
            displayArray = ["True", "False"];
        } else if (displayType == "on") {
            displayArray = ["On", "Off"];
        } else {
           displayArray = displayType.split("/");
        } 

        var target = valueAccessor();  
        var observable = valueAccessor()
        var interceptor = ko.computed(function() {
            return observable() ? displayArray[0] : displayArray[1];
        });

        ko.applyBindingsToNode(element, { text: interceptor });
        ko.applyBindingsToNode(element, { click: function(){ target (!target())} });
    }
};

像这样应用(第二个参数是可选的):

<span data-bind="inlineToggle: alert, type: 'on'"></span>

小提琴还包含一个 forselectmulti-select,但现在多选会导致显示跳转。我需要解决这个问题。

于 2012-11-13T01:43:32.540 回答
1

即使答案已经被接受,我相信我找到了更好的解决方案,所以我想分享它。

我最终使用了这里的文档http://knockoutjs.com/documentation/custom-bindings-controlling-descendant-bindings.html#example-supplying-additional-values-to-descendant-bindings

并提出了这个装订草稿:

ko.bindingHandlers['textinlineeditor'] = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

        var observable = valueAccessor();
        var value = ko.utils.unwrapObservable(observable);

        var saveHandler = allBindingsAccessor().editorsavehandler || function (newValue) { observable(newValue); return true; };
        var inputType = allBindingsAccessor().editorinputtype || "text";            

        var vm = new inlineEditorViewModel({ val: value, saveHandler: saveHandler });

        $(element).append("<span data-bind=\"text: editableValue, hidden: editing\"></span>");
        $(element).append("<input type=\"" + inputType + "\" data-bind=\"value: editableValue, visible:editing\"/>");
        $(element).append("<div class=\"pull-right\"></div>");
        $(element).find("div.pull-right").append("<span class=\"glyphicon glyphicon-edit\" aria-hidden=\"true\" data-bind=\"click: edit, hidden: editing\"></span>");
        $(element).find("div.pull-right").append("<span class=\"glyphicon glyphicon-check\" aria-hidden=\"true\" data-bind=\"click: save, visible:editing\"></span>");
        $(element).find("div.pull-right").append("<span class=\"glyphicon glyphicon-remove-circle\" aria-hidden=\"true\" data-bind=\"click: cancelSave, visible:editing\"></span>");

        var innerBindingContext = bindingContext.extend(vm);
        ko.applyBindingsToDescendants(innerBindingContext, element);

        return { controlsDescendantBindings: true };
    }
};

我在代码中使用的模型是

var inlineEditorViewModel = function (init) {
    var self = this;

    self.editableValue = ko.observable(init.val);
    self.lastEditableValue = ko.observable(init.val);

    self.editing = ko.observable(false);

    self.edit = function () {
        self.editing(true);
    };

    self.save = function () {
        if (init.saveHandler(self.editableValue())) {
            self.lastEditableValue(self.editableValue());
            self.editing(false);
        }
    };

    self.cancelSave = function () {
        self.editableValue(self.lastEditableValue());
        self.editing(false);
    };
};

在您的 html 中,您会像使用它一样使用它

<div data-bind="textinlineeditor: name, editorsavehandler: saveName"></div>

注意:我使用的是 Bootstrap,所以这是绑定 html 中的图标的来源。

于 2015-05-28T21:35:30.613 回答