Reputation: 67
I've created a custom binding to use as a color picker.
<ul data-bind="colorPicker: selcol"></ul>
It creates 10 inline divs each representing other color. When I click a div the color is selected. I have a problem with assigning the 'selected; css class to selected div. I try to use css binding inside custom binding but this doesn't work. It only selects initial div which stays selected even after selecting other div.
Please check the example: http://jsfiddle.net/zbkkzdsp/Jbvvq/
Thanks for any help. If you have any hints or comments to my code, please let me know. I'm quite new with knockout and will take any chance to learn more.
Upvotes: 1
Views: 1169
Reputation: 1690
It seems like you're doing a lot of fancy stuff with computed values in your custom binding, so I would recommend creating view models for your colors.
First define a view model for each individual color:
var ColorModel = function(options) {
var self = this;
// Keep a reference to the parent picker for selection
self.picker = options.picker;
// The CSS value of the color
self.color = ko.observable(options.color || 'transparent');
// A flag denoting whether this color is selected
self.selected = ko.observable(options.selected || false);
// This will be called when the corresponding color link is clicked
// Note that we're not doing any event binding with jQuery as with your custom binder
self.select = function() {
self.picker.selectColor(self);
};
};
Then a view model for the color picker itself:
var ColorPickerModel = function() {
var self = this;
// The list of all colors
self.colors = ko.observableArray([]);
self.addColor = function(color) {
var newColor = new ColorModel({
picker: self,
color: color
});
self.colors.push(newColor);
return newColor;
};
// Called by individual colors
self.selectColor = function(colorModel) {
// Deselect the current color so we don't select two
var current = self.selected();
if (current) {
current.selected(false);
}
// Mark the color as selected - KO will do the rest
colorModel.selected(true);
// Remember this color as the selected one to deselect later
self.selected(colorModel);
};
// Create at least one default color
var transparent = self.addColor('transparent');
// Keep track of the selected color - set to transparent by default
self.selected = ko.observable(transparent);
transparent.select();
};
Then bind your HTML view to your picker view model:
<div id="color-picker">
<div data-bind="foreach: colors">
<a href="#" data-bind="
style: { 'background-color': $data.color },
css: { 'selected': selected },
click: select"></a>
</div>
<div>
Selected color: <span data-bind="text: selected().color"></span>
</div>
</div>
And tie it all together:
var pickerDiv = document.getElementById('color-picker'),
picker = new ColorPickerModel();
// Add some colors
picker.addColor('red');
picker.addColor('blue');
picker.addColor('green');
picker.addColor('orange');
picker.addColor('purple');
picker.addColor('black');
// Bind Knockout
ko.applyBindings(picker, pickerDiv);
// Add more colors - the view will update automatically
picker.addColor('pink');
Here's a working example: http://jsbin.com/izarik/1/edit
Upvotes: 3