I'm creating a custom binding that will display an anchor that when clicked turns into a textbox. Once the user enters a value and hits the enter key the value would be pushed into the observableArray that is passed to the binding.
The majority of the binding was taken from Ryan Niemeyers example - found here
html
<div data-bind="clickToEdit: { data: items, buttonText: 'New Item' }"></div>
binding
ko.bindingHandlers.clickToEdit = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
var options = valueAccessor() || {};
var editing = ko.observable(false);
var newValue = ko.observable();
var button = $('<a class="btn btn-mini" href="#">' + options.buttonText + '</a>').prepend('<span class="icon-plus"></span>').appendTo(element)[0];
var input = $('<input type="text">').appendTo(element)[0];
ko.applyBindingsToNode(button, {
hidden: editing,
click: function () {
editing(true);
}
});
ko.applyBindingsToNode(input, {
value: newValue,
visible: editing,
hasFocus: editing,
//valueUpdate: 'afterkeydown',
onEnter: function(data) {
debugger;
options.data.push(data);
editing(false);
}
});
}
};
The problem is that in the function that is bound to the onEnter
binding the data parameter is always undefined so the new value is never pushed into the array.
Please see my fiddle for a complete example
Two things that can help:
The applyBindingsToNode
call accepts a third argument where you can provide the context. In some of my samples, the context was irrelevant, because it was writing directly to an observable and did not need the data. So, you can pass context
(or viewModel
) in as the third argument to your second applyBindingsToNode
call.
If I understand what you are trying to do though, then I would think that you could just do something like: options.data.push(new Item(newValue());
and not need to worry about the context/data (which would be the overall view model, as you are in the top-level scope).
Example: http://jsfiddle.net/rniemeyer/Pmns4/