Reputation: 2208
I'm confused about where to call various aspects of childrens' lifecycle in composite components. I do not see the way how one Component may be used in other Component which in turn may be used in other etc. Unfortunately Michael Bolins - 'Closure The Definitive Guide' doesn't gives any examples. Neither I cannot find any such examples in Closure demos or in the internet.
Here is my component with children:
goog.provide('MainToolbar');
goog.require('goog.ui.Button');
goog.require('goog.ui.Container');
goog.require('goog.ui.FlatButtonRenderer');
MainToolbar = function(){
goog.ui.Container.call(this, goog.ui.Container.Orientation.HORIZONTAL);
};
goog.inherits(MainToolbar, goog.ui.Container);
MainToolbar.prototype.createDom = function(){
var this_ = this;
// Pre-render the container, just to do something different.
//hc.render(goog.dom.getElement('main-buttons'));
goog.array.forEach(
['Happy', 'Sleepy', 'Doc', 'Bashful', 'Sneezy', 'Grumpy', 'Dopey'],
function(item) {
var c = new goog.ui.Button(item,
goog.ui.FlatButtonRenderer.getInstance());
c.addClassName('goog-inline-block');
c.setId(item);
this_.addChild(c, true);
});
};
Here is how I call it:
mainToolbar = new MainToolbar();
mainToolbar.render(goog.dom.getElement('main-buttons'));
The problem is that MainToolbar.prototype.createDom calls itself second time and I get
Uncaught Error: The object already contains the key "Happy" from myApp
Probably the addChild should be put to some other place, but to where? Constructor? enterDocument? And how it is supposed to scale?
UPDATE: Here is callstack showing the second call:
MainToolbar.createDom (MainToolbar.js:70)
goog.ui.Component.addChildAt (component.js:1009)
goog.ui.Component.addChild (component.js:913)
(anonymous function) (MainToolbar.js:81)
goog.array.forEach.goog.NATIVE_ARRAY_PROTOTYPES.goog.array.ARRAY_PROTOTYPE_.forEach.l (array.js:179)
MainToolbar.createDom (MainToolbar.js:70)
goog.ui.Component.render_ (component.js:664)
goog.ui.Component.render (component.js:621)
Upvotes: 2
Views: 1158
Reputation: 2427
The addChildAt method of goog.ui.Component (inherited by goog.ui.Container) has a check to make sure that if you are trying to render the child control, the parent must also be rendered. It does this by checking the existence of "this.element_":
(line 1023 in my copy of component.js)
if (!this.element_) {
this.createDom();
}
This is where it's getting duplicated. When you override the createDom method, you need to either manually create this property:
this.element_ = goog.dom.createDom('div');
or just let the inherited class do the work :
goog.base(this, 'createDom');
Generally at the top of the method before any work is done.
Upvotes: 2