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 ...@@ -267,17 +267,13 @@ To hook up the control via data attributes, add the `data-role="multiselect"` at
## Knockout JS Support ## 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** **Define select input**
Note the multiselect: true binding! Note the multiselect: true binding!
<select class="multiSelect" data-bind="multiselect: true, options: Options, selectedOptions: SelectedOptions, optionsValue: $data" multiple="multiple"></select> <select multiple="multiple" data-bind="options: items, selectedOptions: selectedItems, multiselect: multiSelectInitOptions"></select>
**Initialize Bootstrap-multiselect**
$(".multiSelect").multiselect();
**Apply Knockout view model** **Apply Knockout view model**
...@@ -285,7 +281,11 @@ As usual. ...@@ -285,7 +281,11 @@ As usual.
**Notes** **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 ## Roadmap / Todo
......
...@@ -25,19 +25,12 @@ ...@@ -25,19 +25,12 @@
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
}, },
update: 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'); 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'); $(element).multiselect('rebuild');
} else {
$(element).multiselect(ko.utils.unwrapObservable(multiSelectData.initOptions));
} }
} }
}; };
...@@ -48,6 +41,9 @@ ...@@ -48,6 +41,9 @@
this.options = this.getOptions(options); this.options = this.getOptions(options);
this.$select = $(select); this.$select = $(select);
this.originalOptions = this.$select.clone()[0].options; //we have to clone to create a new reference 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 () { this.getFilteredOptions = function () {
if (this.query == '') return this.originalOptions; if (this.query == '') return this.originalOptions;
var query = this.query; var query = this.query;
...@@ -200,7 +196,7 @@ ...@@ -200,7 +196,7 @@
// Build the dropdown and bind event handling. // Build the dropdown and bind event handling.
buildDropdown: function () { 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 options.includeSelectAllOption === true, add the include all checkbox
if (this.options.includeSelectAllOption && this.options.multiple && !alreadyHasSelectAll) { if (this.options.includeSelectAllOption && this.options.multiple && !alreadyHasSelectAll) {
this.$select.prepend('<option value="select-all-option">' + this.options.selectAllText + '</option>'); this.$select.prepend('<option value="select-all-option">' + this.options.selectAllText + '</option>');
...@@ -433,7 +429,7 @@ ...@@ -433,7 +429,7 @@
$('button', this.$container).html(this.options.buttonText(options, this.$select)); $('button', this.$container).html(this.options.buttonText(options, this.$select));
}, },
getSelected: function() { getSelected: function () {
return $('option:selected[value!="select-all-option"]', this.$select); return $('option:selected[value!="select-all-option"]', this.$select);
} }
}; };
......
...@@ -15,6 +15,11 @@ ...@@ -15,6 +15,11 @@
<script type="text/javascript" src="js/bootstrap.js"></script> <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/bootstrap-multiselect.js"></script>
<script type="text/javascript" src="js/prettify.js"></script> <script type="text/javascript" src="js/prettify.js"></script>
<style>
table tr td {
width: 25%;
}
</style>
</head> </head>
<body> <body>
<div class="container"> <div class="container">
...@@ -34,16 +39,21 @@ ...@@ -34,16 +39,21 @@
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. 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> </p>
<table class="table table-striped"> <table class="table table-striped">
<tr>
<td>Select</td>
<td>Selected values</td>
<td>Info</td>
<td></td>
</tr>
<tr> <tr>
<td> <td>
<select multiple="multiple" data-bind="multiselect: { initOptions: multiSelectInitOptions, options: items() }, optionsText: 'text', optionsValue: 'id'"> <select multiple="multiple" data-bind="options: items, selectedOptions: selectedItems, multiselect: multiSelectInitOptions"></select>
</select>
<br />
<span data-bind="text: ko.toJSON(items())" />
</td> </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>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>
<td><button data-bind="click: addItem" class="btn btn-primary">Add item</button>
</td>
</tr> </tr>
</table> </table>
<hr> <hr>
...@@ -58,25 +68,27 @@ ...@@ -58,25 +68,27 @@
var viewModel = function () { var viewModel = function () {
var self = this; var self = this;
self.items = ko.observableArray([ self.items = ko.observableArray([
{ id: 1, text: 'item 1' }, 'Cheese',
{ id: 2, text: 'item 2' }, 'Tomatoes',
{ id: 3, text: 'item 3' }, 'Mozzarella',
{ id: 4, text: 'item 4' }, 'Mushrooms',
{ id: 5, text: 'item 5' }, 'Pepperoni'
]); ]);
self.multiSelectInitOptions = { 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; return self;
}; };
var vm = new viewModel(); var vm = new viewModel();
ko.applyBindings(vm); 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> </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