[SalesForce] Lightning Renderer vs Init Function for Dynamic Component Initialization

Is it better to do dynamic component initialization in a renderer or in an init function in the controller?

For example, the following code could be in an init method or a renderer and it will accomplish the same thing

  $A.createComponent(
                'ui:outputText',
                {
                    "aura:id": "fieldValue",
                    "value": "hello world"
                },
                function (outputField) {

                    if (cmp.isValid()) {
                        var body = cmp.get("v.body");
                        cmp.set("v.body", outputField);
                    }

                }
            )

Edit 2016-06-16:

Adding a little bit more complexity to the question. For simple cases the initialization in the init handler makes sense, but what if events will update attributes that will change which dynamic components are shown in the component? Should the event handlers still be responsible for modifying which dynamic components are shown in the component? If I do it in the render any number of events can change attributes without worrying about how to modify the component but if I do it in the handlers then each one has to be concerned about what to do when attributes are changed. Here's an example (this is not a real world example, tried to write something simple that would illustrate what I'm attempting to understand):

Component:

<aura:component >
<aura:attribute name="number" type="Integer" description="based on the integer a different component will render" default="1"/>
<div onclick="{!c.handleClick}" onkeypress="{!c.handleKeyPress}" tabindex="1">
    {!v.body}
</div></aura:component>

Controller:

({
handleClick : function(cmp, event, helper) {
    var number = cmp.get("v.number");
    ++ number; 
    cmp.set("v.number", number);

},
handleKeyPress: function(cmp, event, helper) {
    var number = cmp.get("v.number");
    -- number; 
    cmp.set("v.number", number);
}})

Renderer:

({
render: function(cmp, helper) {

    var ret = cmp.superRender(); 
    helper.buildComponents(cmp);
    return ret; 
},


rerender: function(cmp, helper) {
    helper.buildComponents(cmp);
}})

Helper:

({
buildComponents : function(cmp) {

    var cmpNumber = cmp.get("v.number"); 
    var components = []; 

    console.log(cmpNumber);

    for(var i=0; i<cmpNumber; ++i) {
        components.push(['ui:outputText', {
            value: "hello world "+i
        }]);
    }

    $A.createComponents(components, function(created, status){
        cmp.set("v.body", created);
    });

}})

Best Answer

Dynamic component creation like the example you provided should be done in the init handler rather than the renderer.

Custom renderers should be used sparingly and really only when you need to override the default rendering behavior.

Related Topic