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

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

  • 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. – Scott Morrison Jun 17 '16 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. – TrevorBliss Jun 17 '16 at 18:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.