Finally i gave solution to my problem by creating a new Lightning Component and including it to the Lightning Component for Account. This component i created has an input field as well as a dropdown list to show the available list items. Onclick, the dropdown gets displayed and onfocusout it gets disappeared. Also, the inputField has an action onchange in order to call Apex Class controller to filter the results while user is Typing!
Component
<!--27/10/2019 George Galaios: This component is created in order to cover Citizenship fields. Those fields are not restricted picklists, so it is needed to accept either values from Picklists or Free Text! -->
<!--27/10/2019 George Galaios: Define the appopriate Attributes.-->
<aura:component controller="ea_PickListController">
<aura:attribute name="objectName" type="String" default="Account"/>
<aura:attribute name="fieldName" type="String" default="ea_Citizenship__c"/>
<aura:attribute name="selectRecordId" type="String"/>
<aura:attribute name="selectRecordName" type="String"/>
<aura:attribute name="Label" type="String" default="{!$Label.c.ea_citizenship}"/>
<aura:attribute name="picklistValues" type="String[]"/>
<aura:attribute name="allListValues" type="String[]"/>
<aura:attribute name="required" type="Boolean" default="false"/>
<aura:attribute name="iconName" type="String" default="utility:identity"/>
<aura:attribute name="LoadingText" type="Boolean" default="false"/>
<aura:attribute name="readonly" type="Boolean" default="false"/>
<aura:attribute name="helpText" type="String" default="Επιλέξτε μία χώρα από την λιστα είτε πληκτρολογήστε μία τιμή της επιλογής σας"/>
<!--27/10/2019 George Galaios: If focus goes out, call closeDropDown Controller function-->
<div onfocusout="{!c.closeDropDown}">
<div class="slds-combobox_container slds-size--1-of-1 slds-p-horizontal_x-small">
<div class="slds-size--1-of-1 slds-p-horizontal_x-small slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click" aura:id="resultBox" aria-expanded="false" aria-haspopup="listbox" role="combobox">
<div class="slds-form-element__control" role="none">
<aura:if isTrue="{!v.readonly}">
<!--27/10/2019 George Galaios: Input Field for Citizenship. When user typing, call searchField Controller function-->
<lightning:input required="{!v.required}" disabled="{!v.readonly}" aura:id="userinput" label="{!v.Label}" name="searchText" value="{!v.selectRecordName}" fieldLevelHelp="{!v.helpText}" class="leftspace"/>
<aura:set attribute = "else">
<!--27/10/2019 George Galaios: Input Field for Citizenship. When user typing, call searchField Controller function-->
<lightning:input required="{!v.required}" disabled="{!v.readonly}" aura:id="userinput" label="{!v.Label}" name="searchText" onchange="{!c.searchField}" onclick="{!c.getPickListValues}" value="{!v.selectRecordName}" isLoading="{!v.LoadingText}" type="search" fieldLevelHelp="{!v.helpText}" class="leftspace"/></aura:set>
</aura:if>
</div>
<!--27/10/2019 George Galaios: Second part display result -->
<div id="listbox-id-1" class="slds-dropdown slds-dropdown_length-with-icon-7 slds-dropdown_fluid" role="listbox">
<ul class="slds-listbox slds-listbox_vertical" role="presentation" >
<aura:iteration items="{!v.picklistValues}" var="serecord" indexVar="hdtv">
<li role="presentation" class="slds-listbox__item">
<!--27/10/2019 George Galaios: Show the list of values that match user's typed criteria. Onmousedown call setSelectedRecord controller function -->
<div data-name="{!serecord}" onmousedown="{!c.setSelectedRecord}" class="slds-media slds-listbox__option slds-listbox__option_entity slds-listbox__option_has-meta" role="option">
<span class="slds-media__figure">
<span class="slds-icon_container slds-icon-standard-account">
<!--27/10/2019 George Galaios: Show icon on the left of results displayed -->
<lightning:icon iconName="{!v.iconName}" class="slds-icon slds-icon slds-icon_small slds-icon-text-default" size="x-small"/>
</span>
</span>
<span class="slds-media__body">
<!--27/10/2019 George Galaios: Display Countries Names -->
<span class="slds-listbox__option-text slds-listbox__option-text_entity">{!serecord}</span>
</span>
</div>
</li>
</aura:iteration>
<!--27/10/2019 George Galaios: If loading, show the appropriate message on the screen -->
<aura:if isTrue="{!v.LoadingText}">
Loading...
</aura:if>
</ul>
</div>
</div>
</div>
</div>
</aura:component>
Controller
//ggalaios @ 27/10/2019
//Lightning Component for Citizenships fields of Account
//Component Controller
({
//When clicking on the component it calls Apex function that fetches the values of the picklist field that is given
getPickListValues : function(component) {
//Check if field is in ReadOnly mode and confirm that it does not already have a value
if ((component.get("v.readonly") == false) && ((component.get("v.selectRecordName") == "" || component.get("v.selectRecordName") == undefined || component.get("v.selectRecordName") == null))) {
component.set("v.LoadingText", true);
var action = component.get("c.getPickListValuesIntoList");
action.setParams({
//set the appropriate params
"objectType": component.get("v.objectName"),
"selectedField": component.get("v.fieldName")
});
action.setCallback(this, function(response) {
var list = response.getReturnValue();
component.set("v.picklistValues", list);
component.set("v.allListValues", list);
component.set("v.LoadingText", false);
var resultBox = component.find('resultBox');
$A.util.addClass(resultBox, 'slds-is-open');
//console.log('return value: ' +response.getReturnValue());
})
$A.enqueueAction(action);
}
},
//Function called while user typing on input field
searchField : function(component, event, helper) {
//Capitalize input
component.set("v.LoadingText", true);
var currentText = helper.RemoveAccentsAndCapitalize(event.getSource().get("v.value"));
//Capitalize Component attribute
component.set("v.selectRecordName", currentText);
var resultBox = component.find('resultBox');
//if length of text typed by user > 0 show resultBox, else not show it and assign again PickListValues Attriute the whole list of values
if(currentText.length > 0) {
$A.util.addClass(resultBox, 'slds-is-open');
//Call Apex Class to return the results while user is typing
//console.log('Just before calling Apex... current Text is: ' +currentText);
var action = component.get("c.getSearchList");
action.setParams({
"citizenshipList" : component.get("v.allListValues"),
"value" : currentText
});
action.setCallback(this, function(response){
var STATE = response.getState();
if(STATE === "SUCCESS") {
//console.log('from function is returned...: ' +response.getReturnValue());
component.set("v.picklistValues", response.getReturnValue());
component.set("v.LoadingText", false);
if(component.get("v.picklistValues").length == 0) {
$A.util.removeClass(resultBox, 'slds-is-open');
}
}
else if (state === "ERROR") {
var errors = response.getError();
if (errors) {
if (errors[0] && errors[0].message) {
console.log("Error message: " +
errors[0].message);
}
} else {
console.log("Unknown error");
}
}
});
$A.enqueueAction(action);
}
else {
component.set("v.LoadingText", true);
//console.log('case is currentText is zero length');
var action = component.get("c.getPickListValuesIntoList");
action.setParams({
//set the appropriate params
"objectType": component.get("v.objectName"),
"selectedField": component.get("v.fieldName")
});
action.setCallback(this, function(response) {
var list = response.getReturnValue();
component.set("v.picklistValues", list);
component.set("v.allListValues", list);
var resultBox = component.find('resultBox');
component.set("v.LoadingText", false);
$A.util.addClass(resultBox, 'slds-is-open');
})
$A.enqueueAction(action);
}
},
//when user clicks (X) button, set the appropriate Attributes blank.
resetData : function(component, event, helper) {
component.set("v.LoadingText", true);
component.set("v.selectRecordName", "");
component.find('userinput').set("v.readonly", false);
component.set("v.LoadingText", false);
},
//When user selects a record, set it as selected
setSelectedRecord : function(component, event, helper) {
var currentText = event.currentTarget.id;
var resultBox = component.find('resultBox');
$A.util.removeClass(resultBox, 'slds-is-open');
component.set("v.selectRecordName", event.currentTarget.dataset.name);
},
//Function when user clicks outside Component to close the dropdown list
closeDropDown : function(component, event, helper) {
var resultBox = component.find('resultBox');
$A.util.removeClass(resultBox, 'slds-is-open');
component.set("v.LoadingText", false);
},
})
Helper
({
RemoveAccentsAndCapitalize: function(strAccents) {
var strAccents = strAccents.split('');
var strAccentsOut = new Array();
var strAccentsLen = strAccents.length;
var accents = 'ÀÁÂÃÄÅàáâãäåÒÓÔÕÕÖØòóôõöøÈÉÊËèéêëðÇçÐÌÍÎÏìíîïÙÚÛÜùúûüÑñŠšŸÿýŽžάέήύόύϋΰίϊΐώΆΈΉΎΌΆΎΊΏ';
var accentsOut = "AAAAAAaaaaaaOOOOOOOooooooEEEEeeeeeCcDIIIIiiiiUUUUuuuuNnSsYyyZzαεηυουϋϋιϊϊωαεηυοαυιω";
for (var y = 0; y < strAccentsLen; y++) {
if (accents.indexOf(strAccents[y]) != -1) {
strAccentsOut[y] = accentsOut.substr(accents.indexOf(strAccents[y]), 1);
} else
strAccentsOut[y] = strAccents[y];
}
strAccentsOut = strAccentsOut.join('');
return strAccentsOut.toUpperCase(); //@ggalaios return string also capitalized
},
})
Style
.THIS .slds-leftpad{
padding-left: 2rem;
}
.THIS .iconheight{
top: 65%;
}
.THIS .leftspace input {
padding-left:2rem;
}
Apex Class Controller
public class ea_PickListController {
@AuraEnabled
//15/09/2019: George Galaios: Method to get Picklist values
public static List<String> getPickListValuesIntoList(String objectType, String selectedField){
List<String> pickListValuesList = new List<String>();
Schema.SObjectType convertToObj = Schema.getGlobalDescribe().get(objectType);
Schema.DescribeSObjectResult res = convertToObj.getDescribe();
Schema.DescribeFieldResult fieldResult = res.fields.getMap().get(selectedField).getDescribe();
List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
//27/10/2019: ggalaios: Check if SelectedField is different than Citizenships. Because in Citizenships we do not want the Choice "Please Select"
if ((selectedField != 'ea_Citizenship__c') && (selectedField != 'ea_Citizenship2__c') && (selectedField != 'ea_Profession__c')) {
pickListValuesList.add('--Παρακαλώ Επιλέξτε--');
}
for( Schema.PicklistEntry pickListVal : ple){
pickListValuesList.add(pickListVal.getLabel());
}
return pickListValuesList;
}
@AuraEnabled
//27/10/2019 George Galaios: This method is called while user is typing (searching for Citizenship)
public static List<String> getSearchList(List<String> citizenshipList, String value) {
//Initiate the list that is going to be returned
List<String> searchResultList = new List<String>();
try {
//for every item of the list check if what user has typed is contained in the List of Citizenships
for (Integer i=0; i<citizenshipList.size(); i++) {
if (citizenshipList[i].contains(value)) {
searchResultList.add(citizenshipList[i]);
}
}
} catch (Exception e) {
system.debug('exception caught: ' +e.getMessage());
}
return searchResultList;
}
}
Apex Class Controller Test
@isTest
//Test class for ea_PickListController Apex Class
public class ea_PickListControllerTest {
@isTest Public static void getPickListValuesIntoListTest() {
ea_PickListController.getPickListValuesIntoList('Account', 'ea_CustomerType__c');
}
//Test getSearchList method
@isTest public static void getSearchListTest() {
List<String> testList = new List<String>();
testList.add('ΑΓΓΛΙΑ');
testList.add('ΕΛΛΑΔΑ');
testList.add('ΗΝΩΜΕΝΕΣ ΠΟΛΙΤΕΙΕΣ ΑΜΕΡΙΚΗΣ');
ea_PickListController.getSearchList(testList, 'ΕΛΛ');
}
}
Best Answer
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:
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.