0

I am working on a Multi-Location Case creation component for our community site. The basic premise is that we use Account Contact Relationships to relate a single User/Contact to multiple accounts.

The lightning component queries an Apex Controller to get the list of relationships for the user and builds a Picklist (ui:inputSelectOption) dynamically using the response data. This worked great and generated a picklist with all of the options to choose from.

However, we elected to take it a step further and allow the user to select and store their "Default Support Account Id" in a custom field on the Contact object. So, now what we're trying to do is check if the User has a default set on their contact already, and if so, set the ui:inputSelectOption default value to that account on page load so they don't need to do it every time.

Issue: The default account is being set correctly by comparing the AccountId to the DefaultAccountId variable while iterating through the Relationships, but the issue is that this seems to stick the picklist into a permanently fixed position, and the user cannot change the value anymore.


For example: If the default Account Id was 0010m00000GpdAtSZJ which is Test Account 1 and it matches to one of the AccountIds in the iteration, it sets the value parameter for that ui:inputSelectOption to true, thereby setting Test Account 1 as the active/default value.

If the user attempts to change Test Account 1 to Test Account 2, the picklist still says Test Account 1.


Ultimate question: How do I set a default value for a picklist (ui:inputSelectOption) on page load, but still allow the user to modify it?


Code

Component:

<aura:component implements="forceCommunity:availableForAllPageTypes,force:hasRecordId" access="global" controller="CreateTicketController">
    <aura:attribute name="Relationships" type="AccountContactRelation" />
    <aura:attribute name="DefaultAccountId" type="Id" />
    <aura:attribute name="HasDefaultAccount" type="Boolean" default="false" />
    <aura:handler name="init" value="{!this}" action="{!c.init}" />

    <div class="slds-grid slds-gutters slds-wrap">
        <div class="slds-col slds-size_1-of-1 slds-medium-size_2-of-3 slds-large-size_2-of-3">
            <div class="slds-form-element">
                <label class="slds-form-element__label slds-text-heading_small" for="select-01">Select Account</label>
                <div class="slds-select_container">
                    <ui:inputSelect aura:id="" class="slds-select" change="">
                        <ui:inputSelectOption text="" label="" value="{!!v.HasDefaultAccount}" />
                        <aura:iteration items="{!v.Relationships}" var="option">
                            <ui:inputSelectOption text="{!option.AccountId}" label="{!option.Account.Name}" value="{!option.AccountId == v.DefaultAccountId}" />
                        </aura:iteration>
                    </ui:inputSelect>
                </div>
            </div>
        </div>
    </div>
</aura:component>

JS Controller:

({
    init: function (component, event, helper) {
        var action = component.get("c.getRelatedAccounts");
        var recordId = component.get("v.recordId");
        var userId = $A.get('$SObjectType.CurrentUser.Id');
        var relationships;
        var aloha = '/one/one.app#/alohaRedirect/apex';
        var opt = new Array();
        var defaultAccountId;

        action.setParams({
            "userId": userId
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if(component.isValid() && state == "SUCCESS"){
                relationships = JSON.parse(response.getReturnValue());
                defaultAccountId = relationships[0].Contact.Default_Support_AccountId__c;
                component.set("v.Relationships", relationships);

                if(defaultAccountId){
                    component.set("v.DefaultAccountId", defaultAccountId);
                    component.set("v.HasDefaultAccount",true);
                    console.log('Default ID: ' + defaultAccountId);
                }
            }
        });
        // Invoke the service
        $A.enqueueAction(action);
    }
})

Apex Controller:

public without sharing class CreateTicketController  {

    @AuraEnabled
    public static String getRelatedAccounts(Id userId){
        String recordJSON;
        Id contactId;
        try{
        contactId = [SELECT ContactId FROM User WHERE Id =: userId].ContactId;
        List<AccountContactRelation> accountRelations = [SELECT Id,AccountId,Account.Name,ContactId,Contact.Default_Support_AccountId__c FROM AccountContactRelation WHERE ContactId =: contactId];
        recordJSON = JSON.serialize(accountRelations);
        return recordJSON;
        }catch(Exception ex){
            return '{"error": "' + ex.getMessage() + '"}';
        }
    }
}

1 Answer 1

2

When the expression is reevaluated, the picklist is changing back to the previous value. This happens because changing a value causes an aura:valueChange that ultimately ends up causing the settings to go back to default. Instead, you will want to set the selected value on the ui:inputSelect directly. Because of the "rendering cycle," you should set the picklist value asynchronously after setting the options for the list.

Here's a demonstration about how to properly set the picklist values and the default value:

<aura:application >
    <aura:attribute name="sel" type="String" />
    <aura:attribute name="opts" type="List" />

    <aura:handler name="init" value="{!this}" action="{!c.init}" />

    <ui:inputSelect value="{!v.sel}" label="Demo">
        <aura:iteration items="{!v.opts}" var="opt">
            <ui:inputSelectOption text="{!opt}" value="{!opt}" />
        </aura:iteration>
    </ui:inputSelect>
</aura:application>

({
    init: function(component, event, helper) {
        setTimeout(
            $A.getCallback(
                function() {
                    component.set("v.sel", "there");
                }
            )
        );
        component.set("v.opts", ["hello","there","world"]);
    }
})

Note the use of $A.getCallback to make sure the value change occurs, and the setTimeout function so it will be called after the picklist values render. Note that in your case, since you're going to the server asynchronously, you'll need to set the default value once, via setTimeout, after setting the new picklist values.

3
  • Thanks fox, this helps - I'm just a bit confused on where I should put the setTimeout / getCallback in relation to my action.setCallback and $A.enqueueAction. Should I do this after, or during the getCallback? Oct 4, 2018 at 20:45
  • @MorganMarchese In your function that you're passing to setCallback, you can call setTimeout from there, so it'll kick in after the new options are rendered.
    – sfdcfox
    Oct 4, 2018 at 21:28
  • Thanks @sfdcfox it seems to be working fine with those changes. Oct 5, 2018 at 1:03

You must log in to answer this question.

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