Skip to content

Commit

Permalink
Added synchronization between the selectmenu- and knockout's standard…
Browse files Browse the repository at this point in the history
… value binding.
  • Loading branch information
gvas committed Dec 23, 2014
1 parent b54585d commit e54c708
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 10 deletions.
17 changes: 12 additions & 5 deletions spec/selectmenu.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,24 +61,31 @@
ko.removeNode($element[0]);
});

it('should force knockout\'s value binding to update', function () {
it('should synchronize with knockout\'s value binding', function () {
var $element, vm, autoOpen;

$element = $([
'<select data-bind="selectmenu: {}, value: valueObservable">',
' <option value="1">One</option>',
'<select data-bind="value: valueObservable, selectmenu: {}">',
' <option value="1" selected="selected">One</option>',
' <option value="2">Two</option>',
'</select>'
].join('')).prependTo('body');
vm = { valueObservable: ko.observable() };
ko.applyBindings(vm, $element[0]);

expect(vm.valueObservable()).toEqual('1');
expect(vm.valueObservable()).toBe('1');

// selectmenu -> value
$('.ui-selectmenu-button').click();
$('.ui-selectmenu-menu .ui-menu-item:nth-child(2)').trigger('mouseenter');
$('.ui-selectmenu-menu .ui-menu-item:nth-child(2)').click();

expect(vm.valueObservable()).toEqual('1');
expect(vm.valueObservable()).toBe('2');

// value -> selectmenu
vm.valueObservable('1');

expect($('.ui-selectmenu-text').text()).toBe('One');

ko.removeNode($element[0]);
});
Expand Down
23 changes: 18 additions & 5 deletions src/selectmenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ define(

BindingHandler.call(this, 'selectmenu');

this.after = ['value'];
this.options = ['appendTo', 'disabled', 'icons', 'position', 'width'];
this.events = ['change', 'close', 'create', 'focus', 'open', 'select'];
this.hasRefresh = true;
Expand All @@ -26,11 +27,13 @@ define(
Selectmenu.prototype = utils.createObject(BindingHandler.prototype);
Selectmenu.prototype.constructor = Selectmenu;

Selectmenu.prototype.init = function (element, valueAccessor) {
Selectmenu.prototype.init = function (element, valueAccessor,
allBindingsAccessor) {
/// <summary>Connects the view model and the widget via the isOpen property.
// </summary>
/// <param name='element' type='DOMNode'></param>
/// <param name='valueAccessor' type='Function'></param>
/// <param name='allBindingsAccessor' type='Object'></param>
/// <returns type='Object'></returns>

var value, result;
Expand All @@ -41,7 +44,7 @@ define(
result = BindingHandler.prototype.init.apply(this, arguments);

// maintain the isOpen option
if (value.isOpen) {
if (value.hasOwnProperty('isOpen')) {
ko.computed({
read: function () {
if (ko.utils.unwrapObservable(value.isOpen)) {
Expand All @@ -63,9 +66,19 @@ define(
});
}

// Trigger a change event on the underlying select element when the user
// selects an option. This way knockout's value- and selectedOptions bindings
// can react to the change.
// synchronize the selected option with knockout's standard value binding
if (allBindingsAccessor().hasOwnProperty('value')) {
ko.computed({
read: function () {
ko.utils.unwrapObservable(allBindingsAccessor().value);
$(element).selectmenu('refresh');
},
disposeWhenNodeIsRemoved: element
});
}

// Notify knockout's value- and selectedOptions bindings that the selected
// option has been changed.
this.on(element, 'change', function () {
$(element).trigger('change');
});
Expand Down

0 comments on commit e54c708

Please sign in to comment.