4

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);
    });

}})

1 Answer 1

2

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.

2
  • I added a little bit more detail to the question. I'm wondering if the answer is as simple as avoid them as much as possible or if it's a little more nuanced than that and if there are good use cases for their use. Commented Jun 17, 2016 at 12:55
  • For your edit instead of using the renderer to update the dynamically created components, I would add change handlers to the relevant attributes. For example, <aura:handler name="change" value="{!v.number}" action="{!c.updateComponents}"/> which will call your controller method whenever v.number is changed and from there you can drop in to your buildComponents logic to recreate components based on the new attribute values. Commented Jun 17, 2016 at 18:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .