Reputation: 3514
I have this custom binding that updates an observable with the data for the focused child element of the element that is is applied to:
ko.bindingHandlers.selected =
init: (element, valueAccessor) ->
receiver = valueAccessor()
$(element).focusin((event) ->
data = ko.dataFor(event.target)
receiver(data)
)
This works better than the standard hasFocus
binding for the use case where I want some other part of the page to show information about the focused item:
<ul data-bind="foreach: items, selected: selectedItem">
<li><a href="#" data-bind="text: name"></a></li>
</ul>
<p data-bind="with: selectedItem">
Selected: <span data-bind="text: name"></span>
</p>
Now I want to make this a two-way binding, so that I can change selectedItem
from my script code, and make the correct list element focused with $.focus()
. Any ideas how to extend the binding to work in both ways?
I realize that I may need to use the "control descendant bindings" approach, and not be able to apply the binding to the same element as the foreach
binding, but that's fine. The problem I have is that the child element doesn't seem to be bound when the update function is called (dataFor
returns undefined).
Upvotes: 2
Views: 644
Reputation: 139798
You can walk through the descendant elements in your update
function and check which element to focus using the ko.dataFor
:
update: (element, valueAccessor) ->
receiver = valueAccessor()
item = receiver()
$(element).find("*").each((index, elem) ->
if (item == ko.dataFor(elem))
$(elem).focus()
)
Demo JSFiddle.
Upvotes: 1
Reputation: 11577
I am not sure what you have decided to create a custom binding for finding out a selected item in a collection and storing it in an observable?
You can simply capture an event and find out the selected item:
var data = [
{ "Id" : 0, "Name" : "Item0" },
{ "Id" : 1, "Name" : "Item1" },
{ "Id" : 2, "Name" : "Item2" },
{ "Id" : 3, "Name" : "Item3" },
{ "Id" : 4, "Name" : "Item4" },
{ "Id" : 5, "Name" : "Item5" },
{ "Id" : 6, "Name" : "Item6" },
{ "Id" : 7, "Name" : "Item7" }
]
function vm(){
var self = this;
self.items = ko.observableArray(data);
self.selectedItem = ko.observable();
self.selectItem = function(item){
self.selectedItem(item);
}
self.select3rd = function(){
self.selectedItem(self.items()[2]);
}
}
ko.applyBindings(new vm());
Html:
<ul data-bind="foreach: items">
<li><a href="#" data-bind="text: Name, event: { focus : $parent.selectItem }, attr: { 'tabindex' : $index }"></a></li>
</ul>
<p>Selected item: <span data-bind="text: ko.toJSON(selectedItem)"></span></p>
<button data-bind="click: select3rd">Select 3rd item</button>
Upvotes: 0