1

У меня есть 2 Bacon.jQuery Models (но проблема может быть проиллюстрирована любым беконом Observable).combWith ​​vs onValues ​​in Bacon.js

У меня есть 3 коробки со списком: foo, bar и quux. bar зависит от foo и quux зависит от комбинации: bar и quux. Существует функция findQuux, которая находит значение для quux combobox от foo и bar.

Если пользователь меняет foo combobox, выбираются значения в bar и quux. Вот рабочая реализация quux выбора:

// WORKS 
var quuxBus = new Bacon.Bus() 
Bacon.onValues(fooModel, barModel, function (foo, bar) 
{ 
    quuxBus.push(findQuux(foo, bar)) 
}) 
quuxModel.addSource(quuxBus.toProperty('quux4')) 

Существует небольшая проблема с этим решением, как мне нужно 'quux4' хак, чтобы установить quux правильно на странице загрузки. Но следующее простое решение не работает на всех:

// DOESN'T WORK 
var quuxCombo = Bacon.combineWith(findQuux, fooModel, barModel) 
quuxModel.addSource(quuxCombo) 

Проблема заключается в том, что findQuux ожидает действительное сочетание foo и bar и аварий при скармливании невозможной комбинации, для которых quux не может быть найден.

Решение onValues/push работает, потому что findQuux вызывается только один раз, когда пользователь меняет foo combobox. Решение bacon.combineWith не работает, потому что findQuux вызывается дважды.

Каков рекомендуемый способ реализации источника данных для quuxModel? Кодирование findQuux - это не вариант.

Полный код можно найти на http://jsfiddle.net/5zp4D/8/

Update: Есть уже разумные значения для foo и bar от загрузки страницы. Как видно из скрипичной ссылки fooModel инициализируется с явным значением, и barModel пересчитывается из этого начального значения:

var fooModel = Bacon.$.selectValue(fooDom, 'foo2-value') 
var barModel = Bacon.$.selectValue(barDom) 

barModel.addSource(fooModel.map(function (x) 
{ 
    return json[x][1].val 
})) 

foo и bar никогда не принимают недопустимые значения. Кроме того, bar заселяется после изменения пользователем foo, поэтому в пользовательском интерфейсе видны только допустимые комбинации.

Проблема с combineWith подхода состоит в том, что, когда пользователь переключает foo затем findQuux функция вызывается дважды с промежуточными значениями, и один из промежуточных комбинаций является неправильным, в то время как комбинация составляющих по отдельности правильно. Я изменил сценарий, чтобы лучше проиллюстрировать проблему: http://jsfiddle.net/5zp4D/12/

Как видно из var json, действительные комбинации: 1-1, 1-2, 2-3, 2-4 и 2-5.

Я раскопал сломанную версию, добавил журнал.При выборе foo1, а затем выберите назад foo2 в первом выпадающем списке, вы получите 4 сообщения в журнале вместо 3:

При загрузке страницы вы видите, что quux значение правильно инициализирован (2-4):

"valid combination of foo2-value and bar4-value" 

при выборе foo1 вместо foo2 вы видите, что findQuuxDef вызывается с 1-4 (foo новый, bar старый), а затем с 2-4 (foo новый, bar новый):

"invalid combination of foo1-value and bar4-value" 
"valid combination of foo1-value and bar2-value" 

Моя проблема заключается в том, что недействительные промежуточные комбинации не происходят с подходом onValues/push, и я хотел бы знать, что такое идиоматический рекомендованный подход к пользовательскому интерфейсу со связанными элементами.

ответ

1

Я бы начал с того, что quuxCombo дал только действительные значения для findQuux. Я бы предпочел иметь разумные значения для входов foo и bar из загрузки страницы, но если это невозможно (почему бы и нет?), Я бы использовал filter на входах. Например,

var quuxCombo = Bacon.combineWith(findQuux, fooModel.filter(validFoo), barModel.filter(validBar)) 

Я предполагаю, однако, что вы хотите начать с некоторого начального значения до того, как существует действительный вход. Для этого я добавил новый метод Property.startWith в Bacon.js 0.6.15. Итак, теперь вы можете

var quuxCombo = Bacon.combineWith(findQuux, fooModel.filter(validFoo), barModel.filter(validBar)).startWith("quux4") 
+0

Обновлен мой вопрос. 'fooModel.filter (validFoo)' не будет работать, потому что 'foo' и' bar' всегда действуют отдельно. Это их комбинация недействительна, поскольку поиск в паре не находит комбинацию в 'var json'. – nponeccop

+0

А, я вижу. Поэтому 'bar' рассчитывается на основе' foo'. Подход onValues ​​работает из-за того, как обновляется атомарность свойств. Результат из «дерева комбинации» свойств будет атомарным, но внутри «дерева» нет атомарности. Таким образом, ваши функции комбинатора могут быть вызваны и для недопустимых комбо. – raimohanska

+0

Итак, у меня нет ответа, готового для вас в то время. Я думаю о том, чтобы добавить какой-то способ указать, что какой-то комбинатор нужно вызывать только для действительных (с атомарным обновлением) комбо ... – raimohanska