我正在尝试使用knockout实现内联编辑。我找到了这个帖子Knockout Inline Edit Binding
并稍微调整一下,以便选择"选择"对于编辑模式。我设法让它工作,除了编辑和查看模式都可见,这不是我的意图。有人可以纠正我的错误。谢谢!
HTML:
<div>
<button id="InputSubmitBtn" type="submit" class="btn btn-custom" data-bind="click: addParam"><span class="glyphicon glyphicon-plus-sign"></span> Add</button>
</div>
<table class="table table-hover table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Value</th>
<th>Data type</th>
</tr>
</thead>
<tbody data-bind="foreach: ParamData">
<tr>
<td data-bind="text: ParamKey" style="width: 20%"></td>
<td data-bind="clickToEdit: ParamValue" style="width: 20%"></td>
<td data-bind="text: DataType" style="width: 20%"></td>
</tr>
</tbody>
</table>
JS:
var format = function (str, col) {
col = typeof col === 'object' ? col : Array.prototype.slice.call(arguments, 1);
return str.replace(/\{\{|\}\}|\{(\w+)\}/g, function (m, n) {
if (m == "{{") {
return "{";
}
if (m == "}}") {
return "}";
}
return col[n];
});
};
var selectOptionsArr = ko.observableArray(['Blue', 'Green', 'Yellow', 'Red']);
var ParamConstr = function (key, value, dataType) {
return {
ParamKey: ko.observable(key),
ParamValue: ko.observable(value),
DataType: ko.observable(dataType)
};
};
var my = my || {};
function Generator() {}
Generator.prototype.rand = Math.floor(Math.random() * 26) + Date.now();
Generator.prototype.getId = function () {
return this.rand++;
};
var idGen = new Generator();
//var ParamData = ko.observableArray([]);
my.viewModel = {
ParamData: ko.observableArray([]),
addParam: function () {
this.ParamData.push(new ParamConstr("$$" + "key1", "Green", "Varchar"));
}
};
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, allBindingsAccessor, viewModel, context) {
var observable = valueAccessor(),
link = document.createElement("a"),
input = document.createElement("select");
var id = idGen.getId();
input.setAttribute("id", id);
input.setAttribute("class", 'selectpicker');
element.appendChild(link);
element.appendChild(input);
var unwrappedArray = ko.toJS(selectOptionsArr);
for (var i = 0; i < unwrappedArray.length; i++) {
var option = document.createElement("option");
option.value = unwrappedArray[i];
option.text = unwrappedArray[i];
input.appendChild(option);
}
var arrayForSelect = [];
for (var j = 0; j < unwrappedArray.length; j++) {
arrayForSelect.push({ value: unwrappedArray[j], id: unwrappedArray[j] });
}
$('.selectpicker').val(allBindingsAccessor().selectedItem());
$('.selectpicker').selectpicker('refresh');
observable.editing = ko.observable(false);
ko.applyBindingsToNode(link, {
text: observable,
hidden: observable.editing,
click: observable.editing.bind(null, true)
});
ko.applyBindingsToNode(input, {
selectedOptions: allBindingsAccessor().selectedItem(), options: arrayForSelect, optionsText: 'value', optionsValue: 'id', selectPicker: {},
value: observable,
visible: observable.editing,
event: {
change: function (data, event) {
observable.editing(false);
return false;
}
}
});
}
};
ko.bindingHandlers.selectPicker = {
after: ['options'], /* KO 3.0 feature to ensure binding execution order */
init: function (element, valueAccessor, allBindingsAccessor) {
var $element = $(element);
$element.addClass('selectpicker').selectpicker();
var doRefresh = function () {
$element.selectpicker('refresh');
}, subscriptions = [];
// KO 3 requires subscriptions instead of relying on this binding's update
// function firing when any other binding on the element is updated.
// Add them to a subscription array so we can remove them when KO
// tears down the element. Otherwise you will have a resource leak.
var addSubscription = function (bindingKey) {
var targetObs = allBindingsAccessor.get(bindingKey);
if (targetObs && ko.isObservable(targetObs)) {
subscriptions.push(targetObs.subscribe(doRefresh));
}
};
addSubscription('options');
addSubscription('value'); // Single
addSubscription('selectedOptions'); // Multiple
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
while (subscriptions.length) {
subscriptions.pop().dispose();
}
});
},
update: function (element, valueAccessor, allBindingsAccessor) {
}
};
ko.applyBindings(my.viewModel);
$(document).ready(function () {
$(".selectpicker").selectpicker();
});
答案 0 :(得分:3)
selectpicker
不是input
节点,因此input
节点上的绑定无法控制它。相反,您需要订阅editing
observable。我没有办法摆脱编辑;你必须选择一个新值才能退出编辑模式。
observable.subscribe(function (newValue) {
observable.editing(false);
});
observable.editing.subscribe(function (newValue) {
$(input).selectpicker(newValue ? 'show' : 'hide');
});
observable.editing.notifySubscribers();