Commit e3dffea6 authored by David Stutz's avatar David Stutz

Merge pull request #69 from luisrudge/ko-integration

Fixes knockout integration issues.
parents 92d46ae3 ae6405b7
......@@ -267,17 +267,13 @@ To hook up the control via data attributes, add the `data-role="multiselect"` at
## Knockout JS Support
Thanks to [Devristo](https://github.com/Devristo) this plugin supports [Knockout JS](http://knockoutjs.com/). For further discussion see [the pull requests](https://github.com/davidstutz/bootstrap-multiselect/pull/17).
Thanks to [Devristo](https://github.com/Devristo) and [Luis Rudge](https://github.com/luisrudge) this plugin supports [Knockout JS](http://knockoutjs.com/). For further discussion see [the pull requests](https://github.com/davidstutz/bootstrap-multiselect/pull/17).
**Define select input**
Note the multiselect: true binding!
<select class="multiSelect" data-bind="multiselect: true, options: Options, selectedOptions: SelectedOptions, optionsValue: $data" multiple="multiple"></select>
**Initialize Bootstrap-multiselect**
$(".multiSelect").multiselect();
<select multiple="multiple" data-bind="options: items, selectedOptions: selectedItems, multiselect: multiSelectInitOptions"></select>
**Apply Knockout view model**
......@@ -285,7 +281,11 @@ As usual.
**Notes**
It is important to initialize the multiselect before applying the view model, since the custom binding code will hook into the onChange method to update the binding.
You have to declare your 'multiselect' binding handler **AFTER** your 'options' binding handler.
Thanks to [@robwesterlund](https://twitter.com/robwesterlund) for the hint :)
> **@robwesterlund** - *@luisrudge The reason is that the multiselect plugin works on the option elements which are in the DOM. However, if you place your bindingHandler before the options bindingHandler, there won't be any option elements in the DOM when you call the multiselect plugin.*
## Roadmap / Todo
......
......@@ -25,19 +25,12 @@
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var multiSelectData = valueAccessor();
var options = multiSelectData.options;
var optionsText = allBindingsAccessor().optionsText;
var optionsValue = allBindingsAccessor().optionsValue;
ko.applyBindingsToNode(element, { options: options, optionsValue: optionsValue, optionsText: optionsText }, viewModel);
var ms = $(element).data('multiselect');
if (ms) {
if (!ms) {
$(element).multiselect(ko.utils.unwrapObservable(valueAccessor()));
} else if (allBindingsAccessor().options().length !== ms.originalOptions.length) {
ms.updateOriginalOptions();
$(element).multiselect('rebuild');
} else {
$(element).multiselect(ko.utils.unwrapObservable(multiSelectData.initOptions));
}
}
};
......@@ -48,6 +41,9 @@
this.options = this.getOptions(options);
this.$select = $(select);
this.originalOptions = this.$select.clone()[0].options; //we have to clone to create a new reference
this.updateOriginalOptions = function() {
this.originalOptions = this.$select.clone()[0].options;
};
this.getFilteredOptions = function () {
if (this.query == '') return this.originalOptions;
var query = this.query;
......@@ -200,7 +196,7 @@
// Build the dropdown and bind event handling.
buildDropdown: function () {
var alreadyHasSelectAll = this.$select[0][0].value == 'select-all-option';
var alreadyHasSelectAll = this.$select[0][0] ? this.$select[0][0].value == 'select-all-option' : false;
//If options.includeSelectAllOption === true, add the include all checkbox
if (this.options.includeSelectAllOption && this.options.multiple && !alreadyHasSelectAll) {
this.$select.prepend('<option value="select-all-option">' + this.options.selectAllText + '</option>');
......@@ -433,7 +429,7 @@
$('button', this.$container).html(this.options.buttonText(options, this.$select));
},
getSelected: function() {
getSelected: function () {
return $('option:selected[value!="select-all-option"]', this.$select);
}
};
......
......@@ -15,6 +15,11 @@
<script type="text/javascript" src="js/bootstrap.js"></script>
<script type="text/javascript" src="js/bootstrap-multiselect.js"></script>
<script type="text/javascript" src="js/prettify.js"></script>
<style>
table tr td {
width: 25%;
}
</style>
</head>
<body>
<div class="container">
......@@ -34,22 +39,27 @@
The best way learning from the examples is using firebug, chrome developer tools or similar tools for your browser. Examine the generated markup and used javascript code.
</p>
<table class="table table-striped">
<tr>
<td>Select</td>
<td>Selected values</td>
<td>Info</td>
<td></td>
</tr>
<tr>
<td>
<select multiple="multiple" data-bind="multiselect: { initOptions: multiSelectInitOptions, options: items() }, optionsText: 'text', optionsValue: 'id'">
</select>
<br />
<span data-bind="text: ko.toJSON(items())" />
<select multiple="multiple" data-bind="options: items, selectedOptions: selectedItems, multiselect: multiSelectInitOptions"></select>
</td>
<td><span data-bind="text: ko.toJSON(selectedItems())" /></td>
<td>Basic knockout multiselect example with select all options enabled. Notice that once an item is added to the collection, the select all option isn't checked anymore because it isn't true anymore.
</td>
<td><button data-bind="click: addItem" class="btn btn-primary">Add item</button>
</td>
</tr>
</table>
<hr>
<p>
&copy; 2012
<a href="http://davidstutz.de">David Stutz</a> - <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License v2.0</a>
<a href="http://davidstutz.de">David Stutz</a> - <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License v2.0</a>
</p>
</div>
</body>
......@@ -58,25 +68,27 @@
var viewModel = function () {
var self = this;
self.items = ko.observableArray([
{ id: 1, text: 'item 1' },
{ id: 2, text: 'item 2' },
{ id: 3, text: 'item 3' },
{ id: 4, text: 'item 4' },
{ id: 5, text: 'item 5' },
'Cheese',
'Tomatoes',
'Mozzarella',
'Mushrooms',
'Pepperoni'
]);
self.multiSelectInitOptions = {
includeSelectAllOption: true
includeSelectAllOption: true,
enableFiltering:true
};
self.selectedItems = ko.observableArray([]);
self.addItem = function() {
self.items.push('new item ' + (self.items().length + 1));
};
return self;
};
var vm = new viewModel();
ko.applyBindings(vm);
//simulating changes on the observable
var t = setInterval(function () {
if (vm.items().length >= 15) clearInterval(t);
vm.items.push({ id: vm.items().length + 1, text: 'item ' + (vm.items().length + 1) });
}, 1000);
</script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment