1

Scenario: I have two picklist 'Description' and 'Status'. If 'Description' is blank and 'status' is changed to 'Done' value, it will show an error message and error message should disappear if 'Status' is changed back to 'Open'.(both of these scenario is working), and if 'Status' is again changed from 'Open' to 'Done', it should show the same error message(this is not working).

Reason- it is not working because component.find('question_answer').length is getting updated to 2 when 'Status' is changed from 'Done' to 'Open'. Question- Cannot figure out why is it getting updated? Component

//1st picklist--Description
<aura:if isTrue="{!question.Answer_Type__c == 'Picklist'}">
<aura:if isTrue="{!v.isVisible}"> //this is used to rerender description picklist
<lightning:select value="{!question.answer}" name="{!question.Id}" aura:id="question_answer" onchange="{!c.changevalue}" required="false" messageWhenValueMissing="{!$Label.c.Answer_Required}">
<option value="">{!$Label.c.FAQ_Please_Select }</option>
<aura:iteration items="{!question.answers}" var="answer">
<option value="{!answer.value}" text="{!answer.label}"></option>
</aura:iteration>
</lightning:select>
</aura:if>

//2nd picklist--Status
<lightning:select name="status " label="Status" value="{!v.selValue}" 
onchange="{!c.questionStatusChange}">
<option value="Open">Open</option>
<option value="Done">Done</option>
</lightning:select>

Controller:

questionStatusChange : function(component, event, helper) { 
   let questions = [];
    let quesLength = component.find('question_answer').length;// this returns undefined when status value is changed for the first time
which is expected since there is only one item in question_answer
but returns 1 when status is changed from 'open' to 'Done' for the 2nd time(not expected)
    if(quesLength === undefined) { 
        questions.push(component.find('question_answer'));
    }
    if(component.get("v.selValue") == 'Done') {// when status is changed to Done
        for(var ques in questions) {
            if(questions[ques].get("v.value") === null || questions[ques].get("v.value") === undefined || questions[ques].get("v.value") === '' ) {
                questions[ques].set("v.required", true);
                questions[ques].showHelpMessageIfInvalid(); //displays error message
            } 
        }

    } else {//when status is changed to open
        for(var ques in questions) {
                questions[ques].set("v.required", false);
                console.log(component.find('question_answer').length);//this still returns undefined as expected
                // setting 'isVisible' to false and then to true to remove the error message

                component.set("v.isVisible", false);  
                component.set("v.isVisible", true);
                console.log(component.find('question_answer').length);//this returns 2, not expected
            }           
    } 
}
2

SOLUTION:

lightning:select does not have proper validity handling. I would recommend to use lightning:combobox instead.

You can show/remove validity like below:

clear : function (component, event, helper) {
    component.find("select").set("v.required",false);
    component.find("select").reportValidity();
},
showError : function (component, event, helper) {
    component.find("select").set("v.required",true);
    component.find("select").reportValidity();
},

Reference: https://developer.salesforce.com/docs/component-library/bundle/lightning:combobox/specification

REASON FOR ABOVE

I have come across this situation quite few times. We face this situation when a component is unrendered and again rendered immediately.

Reason:

Aura framework creates DOM at runtime. So, when an element is unrendered, it will be removed from visible DOM by aura_prod.js and also it will remove internal references to that element. Again when the element has to be rendered, the library will create it and references are added. This function of creation and destruction is async in nature.

So, when you run below code:

component.set("v.isVisible", false);  
component.set("v.isVisible", true);

as its async in nature, by the time 1st callback is invoked, you are adding the element again, and hence 2nd callback will override 1st callback. So, although we have only 1 element in visible DOM, there are 2 references in aura_prod.js. Hence, this will return array.

Solution:

You can use Array.isArray(component.find("question_answer")) as below:

    let question_answer = null;
    if(Array.isArray(component.find("question_answer"))) {
        question_answer = component.find("question_answer")[0];
    } else {
        question_answer = component.find("question_answer");
    }

    // logic using question_answer

You need to be careful that you have unique question_answer in markup for above to work as expected.

Or you should avoid implementing logic which will unrender and rerender immediately.

--- added based on comments -----

When you are changing status to Done, it will be fine and works as expected. When you change status back to Open, you are running below code:

component.set("v.isVisible", false);  
component.set("v.isVisible", true);

After this point, component.find('question_answer') will be array and component.find('question_answer').length will return an integer and will not be undefined anymore. All the status changes henceforth will get component.find('question_answer') as array only

  • I had to write logic which rerenders picklist since there is no inbuilt method to remove error message on certain conditions. – devforce Aug 8 at 12:50
  • But, why does component.find("question_answer") returns an array when Status is changed to 'Done' from 'Open' for the 2nd time even though there is only one item in question_answer.(I am referring to let quesLength = component.find('question_answer').length; line) – devforce Aug 8 at 12:56
  • added in answer – salesforce-sas Aug 8 at 13:15
  • added solution in top of answer – salesforce-sas Aug 9 at 4:05

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.