Search code examples
javascriptrazorknockout.jsobservablecolor-picker

Change properties of an object in an observable array with a Colorpicker


I have to use data bind on the two colours of a header (one for background, one for text), but I don't want to create two separate observables, just an array with a single object with two properties: MainColor and SecondaryColor initialized with a hex value. (A colorpicker for each property changes the colours)

I tried this way, but it doesn't work: (js file)

function mainViewModel() {
var self = this;

    self.model = new function () {
        var model = this;
        model.myColor = ko.observable([{
            MainColor: '#0080C0',
            SecondaryColor: '#001111'
        }]);
    }

/* applyBindings is written in another method */

    self.domUtils = new function () {
        var domUtils = this;

        domUtils.initColorPicker = function (selector) {
            $('#' + selector + ' button').colpick({
                colorScheme: 'light',
                layout: 'rgbhex',
                submit: 0,
                color: function () {
                    if (selector == 'MainColor')
                        self.model.myColor()[0].MainColor;
                    else
                        self.model.myColor()[0].SecondaryColor;
                },
                onChange: function (hsb, hex, rgb, el) {
                    if (selector == 'MainColor')
                        self.model.myColor()[0].MainColor = '#' + hex;
                    else
                        self.model.myColor()[0].SecondaryColor = '#' + hex;                   
                 },  

                onShow: function (elem) {
                    var top = parseFloat($(elem).css('top').replace('px', ''));
                    var availableHeight = $(window).height();
                    if (top + $(elem).height() > availableHeight) {
                        $(elem).css('top', (availableHeight - $(elem).height() - 20) + 'px');
                    }
                }
            });
        };

        domUtils.initColorPickers = function () {
            domUtils.initColorPicker('MainColor');
            domUtils.initColorPicker('SecondaryColor');
        };
}

(cshtml file)

<div class="slideshow" data-bind="style: { 'backgroundColor' : model.myColor().MainColor }">
    <div class="slideshow-header slideshow-elements" data-bind="style: { 'backgroundColor' : model.myColor().MainColor, 'color' : model.MyColor().SecondaryColor }"></div>
    <div class="slideshow-button slideshow-elements" data-bind="style: { backgroundColor : model.myColor().MainColor, color : model.myColor().SecondaryColor }">#Next Class</div>                           
</div>

I already verified that all this code works using single observable variables like:

model.MainColor = ko.observable('#0080C0');

But that's not the way I should follow, any thoughts on what may stop the colours from changing?


Solution

  • The problem might be because MainColor and SecondaryColor themselves are not observables.Knockout's 'observability' does not trickle down automatically.
    Also, since you are using an array, you might be better off using a observableArray instead of a simple observable.

    Your declaration will then become something like :

    model.myColor = ko.observableArray([{
                MainColor: ko.observable('#0080C0'),
                SecondaryColor: ko.observable('#001111')
            }]);
    

    Note: Rest of your code will have to be changed accordingly in light of this.