function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Joseph MurawskiJoseph Murawski 

Losing picklist selected value during page refresh

I have created a lightning component that uses 
<div class="slds-truncate" title="{!v.fieldLabel}">
                                <label class="slds-form-element__label">{!v.fieldLabel}</label> <br />
                                <ui:inputSelect aura:id="inputCell" class="slds-input" value="{!v.fieldData}">
                                    <aura:iteration items="{!v.options}" var="statusOption">   
                                        <ui:inputSelectOption text="{!statusOption.value}" label="{!statusOption.label}" />                                       
                                    </aura:iteration>
                                </ui:inputSelect>
                            </div>
to select from a picklist value.  In the save routine I end with $A.get('e.force:refreshView').fire(); to refresh all the components on the page.  When this takes place, the selected value in the picklist is no longer selected and shows the first value in the list. 
I tried re-calling the doInit function but it fires before the refresh is complete and does not fix this.

Any ideas on what I can do to fix this issue?
 
Best Answer chosen by Joseph Murawski
Joseph MurawskiJoseph Murawski
Khan,

Thanks for talking things through with me.  I figured out my issue.  
<ui:inputSelect aura:id="inputCell" class="slds-input" value="{!v.fieldData}">
      <aura:iteration items="{!v.options}" var="statusOption">  
          <ui:inputSelectOption text="{!statusOption.value}" label="{!statusOption.label}" />                                      
      </aura:iteration>
</ui:inputSelect>

I have this formatted wrong.
I should have options="{!v.options}" in the ui:inputSelect and not include the ui:inputSelectOption at all.

I made the change and it works like a charm.

Again, thanks for looking.

Joe
 

All Answers

Khan AnasKhan Anas (Salesforce Developers) 
Hi Joseph,

Greetings to you!

You can call same method in both handlers, i.e; init and refreshView

Something like this:
 
<!-- handlers-->

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

<aura:handler event="force:refreshView" action="{!c.doInit}" />

We can use the same action method for multiple handlers. Here, you just need to refresh the component. So, it can be done by calling doInit method which will initialize the component again. The init handler is defined to execute some code when the component is initialized. 

If the problem still persists, I suggest you please share the complete code.

I hope it helps you.

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in the future. It will help to keep this community clean.

Thanks and Regards,
Khan Anas
Joseph MurawskiJoseph Murawski
Thanks for the suggestion, I am already doing as you mentioned and the refresh handler is not fixing it.
I went to share the code and it exceeds the 32K limit here.  How do people normally upload the code examples?

 
Khan AnasKhan Anas (Salesforce Developers) 
There is an option to add a code sample.

Please refer below screenshots.

User-added image


User-added image


Regards,
Khan Anas
Joseph MurawskiJoseph Murawski
OK.   If you see any other places where code could be improved/optimized, feel free to share as well.

Component
<aura:component controller="OneFieldLEX" implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <ltng:require styles="/resource/SLDS103/assets/styles/salesforce-lightning-design-system-ltng.css"/>
    <aura:attribute name="recordId" type="String" />
    <aura:handler name="init" action="{!c.doInit}" value="{!this}" />    
    <aura:attribute name="fieldName" type="String"   />
    <aura:attribute name="fieldData" type="String" />
    <aura:attribute name="fieldLabel" type="String" />
    <aura:attribute name="fieldType" type="String" />
    <aura:attribute name="displayMode" type="String" />
    <aura:attribute name="maxLength" type="Integer" />
    <aura:attribute name="displayRows" type="Integer" />
    <aura:attribute name="isAccessible" type="Boolean" />
    <aura:attribute name="options" type="Object[]"/>
    
    <aura:handler event="force:refreshView" action="{!c.doInit}" />
    <aura:if isTrue="{!v.isAccessible == true}">
        <article class="slds-card slds-card--wide">
        <lightning:card >
            <div class="slds-card__header">
                
                <aura:if isTrue="{!v.fieldType == 'Text-OneLine'}"> <!-- Single-Line Text -->
                    <aura:if isTrue="{!v.displayMode == 'Display'}">
                        <div class="slds-truncate" title="{!v.fieldLabel}">
                            <label class="slds-form-element__label">{!v.fieldLabel}</label> <br />
                            <ui:outputText aura:id="inputCell" class="slds-input" value="{!v.fieldData}" />
                        </div>
                        <aura:set attribute="else">
                            <div class="slds-truncate" title="{!v.fieldLabel}">
                                <label class="slds-form-element__label">{!v.fieldLabel}</label> <br />
                                <ui:inputText aura:id="inputCell" class="slds-input" value="{!v.fieldData}" maxlength="{!v.maxLength}" />                            
                            </div>
                        </aura:set>
                    </aura:if>
                </aura:if>
                
                <aura:if isTrue="{!v.fieldType == 'Text-MultiLine'}">  <!-- Multi-Line Text -->
                    <aura:if isTrue="{!v.displayMode == 'Display'}">
                        <div title="{!v.fieldLabel}">
                            <label class="slds-form-element__label">{!v.fieldLabel}</label> <br />
                            <div class="slds-form-element__control slds-border_bottom">
                                <div class="slds-form-element__static">
                                    <p>{!v.fieldData}</p>
                                </div>
                            </div>
                        </div>                    
                        <aura:set attribute="else">
                                <label class="slds-form-element__label">{!v.fieldLabel}</label> <br />
                                <ui:inputTextarea aura:id="inputCell" value="{!v.fieldData}" maxlength="{!v.maxLength}" rows="{!v.displayRows}" />
                        </aura:set>
                    </aura:if>
                </aura:if>
                
                <aura:if isTrue="{!v.fieldType == 'Date'}"> <!-- Date -->
                    <aura:if isTrue="{!v.displayMode == 'Display'}">
                        <div class="slds-truncate" title="{!v.fieldLabel}">
                            <label class="slds-form-element__label">{!v.fieldLabel}</label> <br />
                            <ui:outputDate aura:id="outputCell" value="{!v.fieldData}" format="MM/dd/yyyy"/>            
                        </div>                    
                        <aura:set attribute="else">
                            <div class="slds-truncate" title="{!v.fieldLabel}">
                                <label class="slds-form-element__label">{!v.fieldLabel}</label> <br />
                                <ui:inputDate aura:id="inputCell" value="{!v.fieldData}" format="MM/dd/yyyy" displayDatePicker="true" />
                            </div>
                        </aura:set>
                    </aura:if>
                </aura:if>
                
                <aura:if isTrue="{!v.fieldType == 'Number'}"> <!-- Number -->
                    <aura:if isTrue="{!v.displayMode == 'Display'}">
                        <div class="slds-truncate" title="{!v.fieldLabel}">
                            <label class="slds-form-element__label">{!v.fieldLabel}</label> <br />
                            <p class="slds-truncate"><ui:outputNumber aura:id="outputCell" value="{!v.fieldData}" /></p>
                        </div>
                        <aura:set attribute="else">
                            <div class="slds-truncate" title="{!v.fieldLabel}">
                                <label class="slds-form-element__label">{!v.fieldLabel}</label> <br />
                                <ui:inputNumber aura:id="inputCell" value="{!v.fieldData}" />
                            </div>
                        </aura:set>
                    </aura:if>
                </aura:if>

                <aura:if isTrue="{!v.fieldType == 'Checkbox'}"> <!-- Checkbox -->
                    <aura:if isTrue="{!v.displayMode == 'Display'}">
                        <div class="slds-truncate" title="{!v.fieldLabel}">
                            <label class="slds-checkbox__label">
                                <ui:outputCheckbox aura:id="inputCell" class="slds-output" value="{!v.fieldData}" />
                                &nbsp;&nbsp;{!v.fieldLabel}{!v.fieldData}
                            </label> <br />                            
                        </div>
                        <aura:set attribute="else">
                            <div class="slds-media__body">
                                <div class="slds-media">
                                    <div class="slds-media__figure">
                                        <label class="slds-checkbox" >
                                            <ui:inputCheckbox aura:id="inputCell" label="{!v.fieldLabel}" value="{!v.fieldData}" />
                                            <span class="slds-checkbox--faux"></span>
                                            <span class="slds-form-element__label slds-assistive-text">"{!v.fieldLabel}"</span>
                                        </label>
                                    </div>
                                    <div class="slds-media__body">
                                        <p class="slds-section-title slds-truncate">{!v.fieldLabel}</p>
                                    </div>
                                </div>
                            </div>
                            <!--
                            <div class="slds-wrap slds-grid" title="{!v.fieldLabel}">
                                <ui:inputCheckbox aura:id="inputCell" label="{!v.fieldLabel}" value="{!v.fieldData}" />
                            </div>
							-->
                        </aura:set>
                    </aura:if>
                </aura:if>

                <aura:if isTrue="{!v.fieldType == 'Picklist'}">
                    <aura:if isTrue="{!v.displayMode == 'Display'}">
                        <div class="slds-truncate" title="{!v.fieldLabel}">
                            <label class="slds-form-element__label">{!v.fieldLabel}</label> <br />
                            <ui:outputText aura:id="inputCell" class="slds-input" value="{!v.fieldData}" />
                        </div>
                        <aura:set attribute="else">
                            <div class="slds-truncate" title="{!v.fieldLabel}">
                                <label class="slds-form-element__label">{!v.fieldLabel}</label> <br />
                                <ui:inputSelect aura:id="inputCell" class="slds-input" value="{!v.fieldData}">
                                    <aura:iteration items="{!v.options}" var="statusOption">   
                                        <ui:inputSelectOption text="{!statusOption.value}" label="{!statusOption.label}" />                                       
                                    </aura:iteration>
                                </ui:inputSelect>
                            </div>
                        </aura:set>
                    </aura:if>
                </aura:if>

                <aura:if isTrue="{!v.displayMode == 'Editable'}">
                    <div aura:id="gridActions" class="forceRecordEditActions hidden">
                        <div class="actionsContainer">
                            <button type="button" 
                                    class="slds-button slds-button--brand" 
                                    onclick="{!c.saveEdit}">
                                Save
                            </button>                            
                        </div>
                        
                    </div>            
                </aura:if>
                
            </div>
        </lightning:card> 
        </article>
    </aura:if>
</aura:component>

Controller:
 
({
    doInit: function(component, event, helper) {
        //checkAccess(ID recordId,string fieldName) 
             
        var actionCheckAccess = component.get("c.checkAccess");
        actionCheckAccess.setParams({  
            recordId : component.get("v.recordId"), 
            fieldName : component.get("v.fieldName"),
        });
        actionCheckAccess.setCallback(this, function(a1){
            var state = a1.getState();
            if (state === "SUCCESS") {
                if (a1.getReturnValue() != null)    
                {
                    var results = a1.getReturnValue();
                    //var results = false;
                    component.set("v.isAccessible",results);
                    if(results == true)
                    {
                        var action = component.get("c.getField");
                        action.setParams({  
                            recordId : component.get("v.recordId"), 
                            fieldName : component.get("v.fieldName"),
                        });
                        action.setCallback(this, function(a){
                            var state = a.getState();
                            if (state === "SUCCESS") {
                                if (a.getReturnValue() != null)    
                                {                                    
                                    var results2 = a.getReturnValue();
                                    var parts = [];
                                    parts = results2.split("|");
                                    //alert("results name: " + parts[0] + " value: " + parts[1]);
                                    component.set("v.fieldLabel",parts[0]);
                                    component.set("v.fieldData",parts[1]);                                    
                                }
                            }
                            else
                            {
                                alert("Error");
                            }
                        });
                        $A.enqueueAction(action); 
                    }
                }
            }
            else
            {
                alert("Error");
            }
        });
        $A.enqueueAction(actionCheckAccess); 
        var fieldType = component.get("v.fieldType");
        var myName = component.get("v.fieldName");
        if (fieldType == "Picklist")
        {            
            var actionPL = component.get("c.getPicklistOptions");
            actionPL.setParams({  
                recordId : component.get("v.recordId"), 
                fieldName : myName,
            });
            actionPL.setCallback(this, function(aPL){
                var state = aPL.getState();
                if (state === "SUCCESS") {
                    if (aPL.getReturnValue() != null)    
                    {  
                        var options = aPL.getReturnValue();
                        component.set("v.options",options);
                    }
                }
                else
                {
                    var somethingwickedthiswaycomes = aPL.getError();
                    //alert(somethingwickedthiswaycomes);
                    helper.ToastMe(component, event, helper, "error",  " -- Something went wrong with getting picklist values");
                }
            });
            $A.enqueueAction(actionPL); 
            
        }
        
    },
    saveEdit : function(component, event, helper) {
        var myName = component.get("v.fieldName");
        var myLabel = component.get("v.fieldLabel").toString();
        var fieldType = component.get("v.fieldType")
        var myValue = "";

        myValue = "" + component.find("inputCell").get("v.value");

        var action = component.get("c.saveField");
        action.setParams({  
            recordId : component.get("v.recordId"), 
            fieldName : myName,
            fieldValue : String(myValue),
            fieldType : component.get("v.fieldType"),
        });
        action.setCallback(this, function(a){
            var state = a.getState();
            if (state === "SUCCESS") {
                if (a.getReturnValue() != null)    
                {  
                    var isSaved = a.getReturnValue();
                    if (isSaved == true)
                    {
                        //Display a confirmation Toast
                        helper.ToastMe(component, event, helper, "success", myLabel + " has been updated successfully");
                    }
                    else
                    {
                        helper.ToastMe(component, event, helper, "error", myLabel + " did not update");
                    }
                }
            }
            else
            {
                var somethingwickedthiswaycomes = a.getError();
                //alert(somethingwickedthiswaycomes);
				helper.ToastMe(component, event, helper, "error",  " -- Something went wrong with the save");
            }
        });
        $A.enqueueAction(action); 
        //$A.get('e.force:refreshView').fire();
        //alert("About to take action");  
        //var doinit = component.get('c.doInit');
        //$A.enqueueAction(doinit);
    },
})

Helper:
({
	ToastMe : function(component, event, helper, ToastType, ToastTxt) {
        /**** TYPE CHOICES ****/
        // error
        // warning
        // success
        // info
        // other
        
    	var T_Text = ToastTxt;
        var T_Type = ToastType;
        //alert("Toast Text: " + T_Text + '\r\nToast Type: ' + T_Type);
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
            "title": "",
            "message": ToastTxt,
            "type": T_Type,
            "duration": "1000",
            "mode": "dismissible"
        });
        toastEvent.fire();
    },
})

Apex Controller:
/******************************************
Created:    2017/12/11
CreatedBy:  Joseph Murawski
Purpose:    Lightning component controller to update one field based on objID and field name
******************************************/
public class OneFieldLEX {
	@AuraEnabled
    public static Boolean saveField(Id recordId,string fieldName,string fieldValue,string fieldType)
    {
        Boolean retVal = true;
        Schema.SObjectType targetType = recordId.getSobjectType();
        SObject newSObject = targetType.newSObject();
        newSObject.put('Id',recordId);
        //else if(sfield.getDescribe().getType() == Schema.DisplayType.DATETIME)
        system.debug('FieldValue: ' + fieldValue);
        if (fieldType == 'Number')
        {
            //system.debug('Saving Number: ' + fieldName);
            try{
            newSObject.put(fieldName,Integer.valueOf(fieldValue));  
            } catch (exception e) 
            {
                // Hopefully this means it is a decimal
                //system.debug('Decimal Value: ' + fieldValue);
                newSObject.put(fieldName,Decimal.valueOf(fieldValue));  
            }
        }
        else
        {
            if (fieldType == 'Date')
            {
                system.debug('Saving Date Value: ' + fieldValue);
                newSObject.put(fieldName,Date.valueOf(fieldValue)); 
            }
            else
            {  
            	if (fieldType == 'Checkbox')
            	{
                	system.debug('Saving Boolean Value: ' + fieldValue);
                    if (fieldValue.toUpperCase() == 'TRUE')
                    {
                    	newSObject.put(fieldName,true);     
                    }
                    else
                    {
                        newSObject.put(fieldName,false); 
                    }
                	
            	}
            	else
            	{ 
                    system.debug('Saving String/Picklist Value: ' + fieldValue);
                	newSObject.put(fieldName,fieldValue);
            	}                 
            }        	
        }
        
        try {
        	update newSObject;
        } catch (exception e2) {system.debug('Exception: ' + e2.getMessage());}
        
        return retVal;
    }
    
    //Boolean retVal = OneFieldLEX.checkAccess('0063600000Mb2ulAAB','Description');
    
    @AuraEnabled
    public static Boolean checkAccess(ID recordId,string fieldName)
    {
        boolean isAccessible = false;
        try {
            string sObjName = recordId.getSObjectType().getDescribe().getName();
            string sObjLabel = recordId.getSObjectType().getDescribe().getLabel();
            
            string sqlCmd = 'select ' + fieldName + ' from ' + sObjName + ' where id = \'' + recordId + '\' limit 1';
            sObject sObj = database.query(sqlCmd);
            
            String type=sObjName;
            
            Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
            Schema.SObjectType leadSchema = schemaMap.get(type);
            Map<String, Schema.SObjectField> fieldMap = leadSchema.getDescribe().fields.getMap();            
            
            for (String fName: fieldMap.keySet()) {                
                
                if (fName == fieldName)
                {
                    isAccessible = fieldMap.get(fName).getDescribe().isAccessible();
                }
            }           
        } catch(exception e){system.debug('ERR: ' + e.getMessage());}
       
	    return isAccessible;
    }
    
	@AuraEnabled
    public static string getField(ID recordId,string fieldName)
    {
        system.debug('Getting Field Info');
        string retVal;
        try {
            string sObjName = recordId.getSObjectType().getDescribe().getName();
            string sObjLabel = recordId.getSObjectType().getDescribe().getLabel();
            
            string sqlCmd = 'select ' + fieldName + ' from ' + sObjName + ' where id = \'' + recordId + '\' limit 1';
            sObject sObj = database.query(sqlCmd);
            
            String type=sObjName;
            
            Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
            Schema.SObjectType leadSchema = schemaMap.get(type);
            Map<String, Schema.SObjectField> fieldMap = leadSchema.getDescribe().fields.getMap();            
            
            for (String fName: fieldMap.keySet()) {                
                
                if (fName == fieldName)
                {
                    sObjLabel = fieldMap.get(fName).getDescribe().getLabel();
                    boolean isAccessible = fieldMap.get(fName).getDescribe().isAccessible();
                }
            }
			system.debug('XX Label ' + sObjLabel);
            system.debug('sObj: ' + sObj); 
            retVal = sObjLabel + '|' + CommonFunctions.parseLEXJSON(JSON.serialize(sObj), fieldName);
            system.debug('retVal: ' + retVal);            
        } catch(exception e){system.debug('ERR: ' + e.getMessage());}
       
        return retVal;
    }
    
    //This method will return picklist values to filter task based on its Status
    @AuraEnabled
    public static List<SelectOptions> getPicklistOptions(ID recordId, String fieldName) {
      List<SelectOptions> options = new List<SelectOptions>();
      for(selectoption so : getPicklistValues(recordId, fieldName)) {
        SelectOptions newOption = new SelectOptions(so.getLabel(), so.getValue());
        // setting In Progress as default on the picklist.
        //if(so.getLabel() == 'In Progress') {
        //  newOption.isDefault = true;
        //}
        options.add(newOption);
      }
      return options;
    }

    //this is generic method to get picklist values from picklist fields
    private static list<SelectOption> getPicklistValues(ID recordId, String fieldName){
        
        list<SelectOption> options = new list<SelectOption>();
        // Get the object type of the SObject.
        Schema.SObjectType objType = recordId.getSobjectType();
        // Describe the SObject using its object type.
        Schema.DescribeSObjectResult objDescribe = objType.getDescribe();       
        // Get a map of fields for the SObject
        map<String, Schema.SObjectField> fieldMap = objDescribe.fields.getMap(); 
        // Get the list of picklist values for this field.
        list<Schema.PicklistEntry> values =
           fieldMap.get(fieldName).getDescribe().getPickListValues();
        // Add these values to the selectoption list.
        for (Schema.PicklistEntry ple : values) { 
           options.add(new SelectOption(ple.getLabel(), ple.getValue())); 
        }
        return options;
    }
   
    // this is wrapper class for picklist options to show label, value and default selected
    public Class SelectOptions {
      @AuraEnabled
      public String label{get;set;}
      @AuraEnabled
      public String value{get;set;}
      @AuraEnabled
      public Boolean isDefault{get;set;}

      public SelectOptions(String label, String value) {
        this.label = label;
        this.value = value;
        this.isDefault = false;
      }
    }

    
}

Design:
<design:component >
	<design:attribute name="fieldName" label="Field API Name" default="Name" description="Enter Field API Name" />
	<design:attribute name="displayMode" label="Diaplay Mode" datasource="Editable,Display" default="Editable" description="Select Editable if you wish the user to edit the values, Display if you only wish to show the values" />
	<design:attribute name="fieldType" datasource="Checkbox,Date,Number,Picklist,Text-MultiLine,Text-OneLine" label="Field Value Type" default="Text-OneLine" description="Select how the results should be displayed" />
	<design:attribute name="maxLength" label="Maximum Field Length" default="255" description="Enter the maximum text length allowed for input AS INTEGER" />
	<design:attribute name="displayRows" label="Number of rows to display" default="5" description="Enter the number of vertical rows to display" />
</design:component>

​​​​​​​
 
Khan AnasKhan Anas (Salesforce Developers) 
Hi Joseph, 

There is no problem with the refresh part. It is working fine. In doInit method you are fetching picklist values dynamically and it is storing in ui:inputSelect as it is coming from server. So, on refresh also it is doing the same thing. You are not fetching the record picklist value which is stored in database. If you want to display the stored picklist value then you need to fetch it from the particular record accordingly. 

I hope it helps you! 

Kindly mark this as solved if the information was helpful. It will help to keep this community clean. 

Regards, 
Khan Anas
Joseph MurawskiJoseph Murawski
Thank you for looking, but if you look deeper then you would not have said, "You are not fetching the record picklist value which is stored in database." as I am populating the fieldData field with the selected value from the database.
Khan AnasKhan Anas (Salesforce Developers) 
Oh, my bad! I missed that.
I am implementing your code in my developer org. Can you please share CommonFunctions class as well as there is some dependency on below line of code.

retVal = sObjLabel + '|' + CommonFunctions.parseLEXJSON(JSON.serialize(sObj), fieldName);

Regards,
Khan Anas
Joseph MurawskiJoseph Murawski
public static String parseLEXJSON(String jsonStr,String textVal){
        String value = null;
        if(!String.isBlank(jsonStr)){
            JSONParser parser = JSON.createParser(jsonStr); 
            while(parser.nextToken()!=null){ 
                if(parser.getCurrentToken() == JSONToken.FIELD_Name && textVal.equalsIgnoreCase(parser.getText())){
                    if('emails'.equalsIgnoreCase(textVal)){
                        parser.nextToken();
                        parser.nextToken();
                        system.debug('NExt -'+parser.nextToken()+'-'+parser.getText());                             
                    }
                    parser.nextToken();
                    value = parser.getText();
                    break;
                }
            }
        }
        return value;
    }
Here is the function.  I'm afraid I cannot share the entire class as there is info in it I cannot share, but this should allow you to recreate the component.

 
Joseph MurawskiJoseph Murawski
Khan,

Thanks for talking things through with me.  I figured out my issue.  
<ui:inputSelect aura:id="inputCell" class="slds-input" value="{!v.fieldData}">
      <aura:iteration items="{!v.options}" var="statusOption">  
          <ui:inputSelectOption text="{!statusOption.value}" label="{!statusOption.label}" />                                      
      </aura:iteration>
</ui:inputSelect>

I have this formatted wrong.
I should have options="{!v.options}" in the ui:inputSelect and not include the ui:inputSelectOption at all.

I made the change and it works like a charm.

Again, thanks for looking.

Joe
 
This was selected as the best answer