1

I have a Lightning Aura Component form with several lightning:input elements, and a request to set the cursor/focus to the first input when the component loads.

I have something like this in my component:

<aura:attribute name="myDate" type="Date" />
<aura:attribute name="fruitOptions" type="List" />
<aura:attribute name="fruitOptionSelection" type="String" />

<aura:handler name="render" value="{!this}" action="{!c.onRender}"/>
<aura:handler name="change" value="{!v.myDate}" action="{!c.setFruitOptions}" />

<lightning:input aura:id="field" type="date" name="myDate" label="My Date" required="true" 
    value="{!v.myDate}"/>
<aura:if isTrue="{! !empty(v.fruitOptions) }">
    <lightning:radioGroup aura:id="field" name="myFruitPicker" label="Select a fruit" 
        options="{!v.fruitOptions}" value="{!v.fruitOptionSelection}" />
</aura:if>

In the controller:

onRender : function(component, event, helper) {
    helper.setInitFocus(component);
},

setFruitOptions : function(component, event, helper) {
    helper.setOptions(component);
},

And in the helper:

setInitFocus: function(component) {
    var fields = component.find('field');
    Array.isArray(fields) ? fields[0].focus() : fields.focus();
},

setOptions: function(component) {
    var date = new Date(component.get('v.myDate'));
    var newOptions = null;
    if (date < new Date('2018-01-01')) {
        newOptions = [
            {label: 'Apples', value: 'Apples'},
            {label: 'Pears', value: 'Pears'},
            {label: 'Oranges', value: 'Oranges'}
        ];
    } else {
        newOptions = [
            {label: 'Bananas', value: 'Bananas'},
            {label: 'Pineapples', value: 'Pineapples'}
        ];
    }
    component.set('v.myOptions', newOptions);
}

This works great in the sense that it focuses the cursor on the "My Date" input on load. The problem is that it does this again when I supply a value in the My Date field, which triggers the change handler and eventually causes parts of the component to rerender.

I only want it to execute setInitFocus on the initial rendering, not any subsequent ones. Best approach?

1

Seems obvious in hindsight, but here's how I solved it.

I added this to the component...

<aura:attribute name="renderedOnce" type="Boolean" default="false" />

...And changed the controller onRender method like so...

onRender : function(component, event, helper) {
    if ( !component.get('v.renderedOnce') ) {
        helper.setInitFocus(component);
        component.set('v.renderedOnce', true);
    }
},

I'm still curious if there are ways to extract contextual information out of the render event that could be used in similar scenarios. If anyone knows anything like that, please share!

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.