Newer Version Available

This content describes an older version of this product. View Latest

Events Fired During the Rendering Lifecycle

A component is instantiated, rendered, and rerendered during its lifecycle. A component is rerendered only when there’s a programmatic or value change that would require a rerender, such as when a browser event triggers an action that updates its data.

The component lifecycle starts when the client sends an HTTP request to the server and the component configuration data is returned to the client. No server trip is made if the component definition is already on the client from a previous request and the component has no server dependencies.

Before going into the rendering lifecycle on the client, it’s useful to understand the server-side and client-side processing for component requests in brief. The framework builds the component definition and all its dependencies in the server, including definitions for interfaces, controllers, and actions.. After creating a component instance, the serialized component definitions and instances are sent down to the client. Definitions are cached but not the instance data.

The client deserializes the response to create the JavaScript objects or maps, resulting in an instance tree used to render the component instance. The client locates the custom renderer in the component bundle or uses the default renderer method.

The following image depicts a typical rendering lifecycle of a component on the client, after the component definitions and instances are deserialized.

The rendering lifecycle starts after the init event and ends with the doneRendering event.

  1. The init event is fired by the component service that constructs the components to signal that initialization has completed.
    1swfobject.registerObject("clippy.codeblock-0", "9");<aura:handler name="init" value="{!this}" action="{!.c.doInit}"/>
    You can customize the init handler and add your own controller logic. For more information, see Invoking Actions on Component Initialization.
  2. render() is called to start component rendering. The renderer for aura:component has a base implementation of render(), but your component can override this method in a custom renderer. For more information, see Client-Side Rendering to the DOM.
  3. afterRender() is called to signal that rendering is completed for each of these component definitions. It enables you to interact with the DOM tree after the framework rendering service has inserted DOM elements.
  4. To indicate that the client is done waiting for a response to the server request XHR, the doneWaiting event is fired. You can handle this event by adding a handler wired to a client-side controller action.
  5. The framework checks whether any components need to be rerendered and rerenders any “dirtied” components to reflect any updates to attribute values, for example. Finally, the doneRendering event is fired the end of the rendering lifecycle.
Let’s see what happens when a ui:button component is returned from the server and any rerendering that occurs when the button is clicked to update its label.
1swfobject.registerObject("clippy.codeblock-1", "9");<!-- The uiExamples:buttonExample container component -->
2<aura:component>
3    <aura:attribute name="num" type="Integer" default="0"/>
4    <ui:button aura:id="button" label="{!v.num}" press="{!c.update}"/>
5</aura:component>
1swfobject.registerObject("clippy.codeblock-2", "9");/** Client-side Controller **/
2({
3    update : function(cmp, evt) {
4        cmp.set("v.num", cmp.get("v.num")+1);
5    }
6})

It’s helpful to refer to the ui:button source to understand the component definitions to be rendered. For more information, see https://github.com/forcedotcom/aura/blob/master/aura-components/src/main/components/ui/button/button.cmp. Additionally, HTML tags in the markup are converted to <aura:html> tags.

Note

After initialization, render() is called to render ui:button. ui:button doesn’t have a custom renderer, and uses the base implementation of render(). In this example, render() is called eight times in the following order.
Component Description
uiExamples:buttonExample The top-level component that contains the ui:button component
ui:button The ui:button component that’s in the top-level component
aura:html Renders the <button> tag.
aura:if The first aura:if tag in ui:button, which doesn’t render anything since the button contains no image
aura:if The second aura:if tag in ui:button
aura:html The <span> tag for the button label, nested in the <button> tag
aura:expression The v.num expression
aura:expression Empty v.body expression

When rendering is done, this example calls afterRender() eight times for these component definitions. The doneWaiting event is fired, followed by the doneRendering event.

Clicking the button updates its label, which checks for any “dirtied” components and fires rerender() to rerender these components, followed by the doneRendering event. In this example, rerender() is called eight times. All changed values are stored in a list on the rendering service, resulting in the rerendering of any “dirtied” components.

Firing an event in a custom renderer is not recommended. For more information, see Events Anti-Patterns.

Note

Rendering Nested Components

Let’s say that you have an app myApp.app that contains a component ui:myCmp with a ui:button component.Nested components are rendered in a certain order.

During initialization, the init() event is fired in this order: ui:myCmp, ui:button, and myApp.app. The doneWaiting event is fired in the same order. Finally, the doneRendering event is also called in the same order.

Customizing the doneWaiting Handler

The doneWaiting event is fired to signal that the client is done waiting for a response to a server request, and is sometimes preceded by a waiting event. The waiting event is fired when an action is sent to the server, such as when a server-side action is added using $A.enqueueAction() and subsequently run. You can listen for this event by using the following syntax and adding its controller logic.
1swfobject.registerObject("clippy.codeblock-3", "9");<aura:handler event="aura:waiting" action="{!c.waiting}"/>
2<aura:handler event="aura:doneWaiting" action="{!c.doneWaiting}"/>
For example, you might want to display a spinner during a waiting event and hide it when the doneWaiting event is fired. This example either adds or remove a CSS class depending on which event is fired.
1swfobject.registerObject("clippy.codeblock-4", "9");({
2  waiting: function(cmp, event, helper) {
3    $A.util.addClass(cmp.find("spinner").getElement(), "waiting");
4  },
5  doneWaiting: function(cmp, event, helper) {
6    $A.util.removeClass(cmp.find("spinner").getElement(), "waiting");
7  }
8})

Customizing the doneRendering Handler

You can listen for this event by using the following syntax and add its controller logic.
1swfobject.registerObject("clippy.codeblock-5", "9");<aura:handler event="aura:doneRendering" action="{!c.doneRendering}"/>
For example, you want to customize the behavior of your app after it’s finished rendering the first time but not after subsequent rerenderings. Create an attribute to determine if it’s the first rendering.
1swfobject.registerObject("clippy.codeblock-6", "9");<aura:attribute name="isDoneRendering" type="Boolean" default="false"/>
1swfobject.registerObject("clippy.codeblock-7", "9");({
2  doneRendering: function(cmp, event, helper) {
3    if(!cmp.get("v.isDoneRendering")){
4      //do something after app is first rendered
5    }
6  }
7})