[SalesForce] lightning:select – Set default value based on sObject List from apex controller

Trying to populate an lightning attribute if a single record exists and if multiple records exists would like to provide the user a select list to choose the record then set the attribute.

I cannot seem to get the lightning:select to get its value to be set:

Component

<aura:component description="Account_Selection" controller="MyController">
        <!-- Handle component initialization in a client-side controller -->
        <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

        <!-- The list of accounts to display -->
        <aura:attribute name="accounts" type="Account[]"/>

        <lightning:select aura:id="a_opt" name="a_opt" label="Accounts"  onchange="{!c.onSelectChange}">
            <aura:iteration items="{!v.accounts}" var="account">
                <option value="{!account.Id}">{!account.Name}</option>
            </aura:iteration>
        </lightning:select>
</aura:component>

Controller

({
    doInit : function(component, event, helper) {
        //console.log('here');
        helper.getAccounts(component);
    },

    onSelectChange : function(component, event, helper) {
        // Print out the selected value
        var selected = component.find("a_opt").get("v.value");
        console.log('@@@@@@@: ' + selected);
    }
})

Helper

({
    getAccounts : function(cmp) {
         var action = cmp.get("c.getAccounts");
         action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                cmp.set("v.accounts", response.getReturnValue());
                cmp.set("v.accountId","ANIDTOTESTTHESET");
                var sel = cmp.find('a_opt');
                sel.set("v.value","ANIDTOTESTSETTINGTHEVALUE");
            }
        });
         $A.enqueueAction(action);
    }
})

Now, the select DOES show the available select options but I cannot for the life of me get the value to be set via the code.

The above component is within a parent component as so:

<c:Account_Selection aura:id="a_selection"/>

The parent component has an attribute

<aura:attribute name="accountId" type="Id"/>

What I would like to happen:

  1. If only one account record returned from the apex controller, set the value of the accountId attribute to the Id of that record
  2. If multiple accounts found, set the default value of the select list to a specific value and set the attribute value
  3. If user selects a value then set the value of the attribute

I have tried everything I can think of searched but cannot get it to work. The select list has all the options but the first value seems to always be selected regardless of the value I attempt to set.

The outPutText does not have any value despite explicitly setting it from the component..

Any ideas how to make this work?

Update

I think the issue is the "cmp" is not the lightning component it is the apex controller? How do i get a reference back to the component on the callback?

Best Answer

Setting the options doesn't actually cause the rendering to happen. So, the value you're setting is ignored because it isn't valid at the time. The solution is to use another callback post-rendering. Here's an example app I wrote that demonstrates this:


<aura:application extends="force:slds" controller="LightningAccountController">
    <aura:attribute name="accounts" type="Account[]" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

    <lightning:select label="Choose 1" name="a_opt" aura:id="a_opt" onchange="{!c.change}">
        <aura:iteration items="{!v.accounts}" var="account">
            <option value="{!account.Id}">{!account.Name}</option>
        </aura:iteration>
    </lightning:select>
</aura:application>

// Controller
({
    doInit: function(component, event, helper) {
        // Request from server
        var action = component.get("c.getAccountList");
        action.setCallback(this, function(result){
            var accounts = result.getReturnValue();
            console.log(accounts);
            component.set("v.accounts", accounts);
            // Let DOM state catch up.
            window.setTimeout(
                $A.getCallback( function() {
                    // Now set our preferred value
                    component.find("a_opt").set("v.value", accounts[4].Id);
                }));
        });
        $A.enqueueAction(action);
    }
})

// Apex class
global class LightningAccountController {
    @AuraEnabled global static Account[] getAccountList() {
        return [SELECT Name FROM Account LIMIT 10];
    }
}
Related Topic