1

Using can.js I have this control:

var Test_Controller = can.Control({
    defaults: {
        option1: 'option1',
        option2: 'option2',
        option3: {
            nested1: 'nested1',
            nested2: 'nested2',
            nested3: 'nested3'
        }
    }
}, {
    init: function() {
        if ($(this.element).attr('data-newtext')) {
            this.options.option3.nested2 = $(this.element).data('newtext');
        }

        $(this.element).text(this.options.option3.nested2);
    }
});

.. and this markup:

<div class="instance1" data-newtext="newtext"></div>
<div class="instance2"></div>

..then if I create instances of that control like this:

var instance1 = new Test_Controller('.instance1', {});
var instance2 = new Test_Controller('.instance2', {});

What I would expect to see is 2 divs, one with the word newtext inserted and the other with the word nested2 but what I actually see is 2 divs with the word newtext inserted.

If I change my options object so that it doesn't use nesting, but puts all the options at the top level, then I have no problem.

So it would seem that canJS doesn't merge nested objects correctly when merging options with defaults. Is this the case? Does anyone have any clever ideas how I might be able to support this feature without forking? Or am I missing something obvious? It'd save me having to write lots of laborious options creation code if I could do this.

ramblinjan
  • 6,578
  • 3
  • 30
  • 38
AndyFlan
  • 11
  • 1
  • 4
  • it seems that can.js merges the defaults with the instance options at some point, but does not make a deep copy. if you can access the defaults object from your init function then you can make that deep dopy yourself, or use it directly – tikider Sep 18 '13 at 09:24

1 Answers1

1

As @tikider pointed out, can.extend uses the libraries native .extend (in most cases probably $.extend) which does not do a deep clone by default. You should however be able to overwrite the Controls setup and make a deep extend:

var Test_Controller = can.Control({
    defaults: {
        option1: 'option1',
        option2: 'option2',
        option3: {
            nested1: 'nested1',
            nested2: 'nested2',
            nested3: 'nested3'
        }
    }
}, {
    setup: function( element, options ) {
        var allOptions = $.extend(true, {}, this.constructor.defaults, options);
        return can.Control.prototype.setup.call(this, element, allOptions);
    },

    init: function() {
        if (this.element.attr('data-newtext')) {
            this.options.option3.nested2 = this.element.data('newtext');
        }

        this.element.text(this.options.option3.nested2);
    }
});
Daff
  • 43,734
  • 9
  • 106
  • 120