【发布时间】:2012-11-01 12:18:32
【问题描述】:
我去寻找一个淘汰的内联编辑绑定,但我发现的唯一一个有external dependencies,而不是 jQuery,或used more than just a binding。
所以我想我会分享我想出的简单答案(当然欢迎其他答案,尤其是那些只使用淘汰赛的答案)。
【问题讨论】:
标签: jquery knockout.js inline-editing
我去寻找一个淘汰的内联编辑绑定,但我发现的唯一一个有external dependencies,而不是 jQuery,或used more than just a binding。
所以我想我会分享我想出的简单答案(当然欢迎其他答案,尤其是那些只使用淘汰赛的答案)。
【问题讨论】:
标签: jquery knockout.js inline-editing
作为替代方案:我用于内联编辑的代码如下所示:
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
});
}
};
【讨论】:
内,因为你没有设置宽度,它不会很好地排列。一个问题:为什么要创建一个隐藏绑定,而不仅仅是visible: !observable.editing?
applyBindingsToNode 时,我们需要传递一个可观察/计算的对象,当绑定运行时它会被解包。如果您只是将其传递给!observable.editing(),那么它将是一个永远不会触发更改的静态值。另一种选择是在处理程序中定义一个计算值,它返回与editing 子可观察对象相反的值,例如:jsfiddle.net/rniemeyer/Rg8DM/2。是的,它对宽度没有任何作用。
这是我的inline edit binding (fiddle),不过它依赖 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>
小提琴还包含select 和multi-select 的一个,但现在多选会导致显示跳转。我需要解决这个问题。
【讨论】:
尽管答案已经被接受,但我相信我找到了更好的解决方案,所以我想分享它。
并提出了这个装订草稿:
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 中的图标的来源。
【讨论】: