2014-01-17 3 views
2

У меня есть этот обычай связывание, который обновляет наблюдаемый с данными для сфокусированного дочернего элемента элемента, который применяется к:TwoWay фокус связывание в knockout.js

ko.bindingHandlers.selected = 
    init: (element, valueAccessor) -> 
    receiver = valueAccessor() 
    $(element).focusin((event) -> 
     data = ko.dataFor(event.target) 
     receiver(data) 
    ) 

Это работает лучше, чем стандартная hasFocus обязательный для случая использования, где я хочу какая-то другая часть страницы, чтобы показать информацию о сфокусированном пункте:

<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> 

Теперь я хочу, чтобы сделать это двухстороннее связывание а, так что я могу изменить selectedItem от моего сценария кода и сделать правильный элемент списка, сфокусированный на $.focus(). Любые идеи о том, как расширить привязку к работе в обоих направлениях?

Я понимаю, что мне может понадобиться подход «привязки к потокам потомков» и не сможет применить привязку к тому же элементу, что и привязка foreach, но это нормально. Проблема заключается в том, что дочерний элемент не привязан при вызове функции обновления (dataFor возвращает неопределенный).

+0

Можете ли вы опубликовать скрипку, где вы находитесь, и немного больше информации о том, чего вы пытаетесь достичь? –

+0

Попробуйте следующее: http://jsfiddle.net/ptWxF/2/ Это не очень хорошо работает в обычном браузере, но это для платформы с пространственной навигацией, где акцент важен. – Ropez

+0

Еще одно обновление, с некоторым стилем http://jsfiddle.net/ptWxF/3/ – Ropez

ответ

1

Вы можете пройти через элементы потомков в вашей update функции и проверьте, какой элемент следует сфокусировать, используя ko.dataFor:

update: (element, valueAccessor) -> 
    receiver = valueAccessor() 
    item = receiver() 
    $(element).find("*").each((index, elem) ->  
     if (item == ko.dataFor(elem)) 
     $(elem).focus() 
    ) 

Демо-версия JSFiddle.

+0

Существуют потенциальные проблемы, такие как поиск элемента, который соответствует элементу, но не настраиваемый, скрытый и т. Д., Но общая идея работает. Я надеялся, что у нокаута есть что-то, что срабатывало против dataFor, но я думаю, что это невозможно вообще. – Ropez

0

Я не уверен, что вы решили создать пользовательскую привязку для поиска выбранного элемента в коллекции и сохранения его в наблюдаемом?

Вы можете просто захватить событие и выяснить, выбранный пункт:

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> 

And the fiddle is here

+0

Все дело в том, чтобы контролировать и контролировать индикатор фокуса браузера, не обрабатывать события мыши. – Ropez

+0

обновлено, чтобы не использовать события мыши. все браузеры без веб-браузера фокусируются при нажатии на якорь, но webkit требует tabindex, чтобы активировать это (я думаю, что это известная ошибка). – XGreen

+0

. Если вам нравится, вы также можете изменить tabindex на $ index + 1, поэтому tabindex первого не равен нулю – XGreen

Смежные вопросы