3

I am building a Lightning Component form with sections. I want to display a big check mark icon on the section if all the rendered lightning:input fields are filled out.

I have successfully tested this approach:

Markup:

<lightning:input aura:id="fieldId" type="number" name="input1" required="true" 
    label="Enter a number" />
<lightning:input aura:id="fieldId" type="number" name="input2" required="true" 
    label="Enter another number" />
<lightning:button variant="brand" label="Check" value="check" 
    onclick="{!c.testMe}"/>

Controller:

testMe : function(component) {

    var allComplete = component.find('fieldId').reduce(function (validSoFar, inputCmp) {
        return validSoFar && !inputCmp.get('v.validity').valueMissing;
    }, true); 
    if (allComplete) {
        console.log('All fields complete!');
    } else {
        console.log('Some fields are missing values.');
    }
},

The problem arises when I start making the form dynamic using aura:if to conditionally hide lightning:input fields.

If I change my markup to this, the function fails and nothing shows up in the console:

<lightning:input aura:id="fieldId" type="number" name="input1" required="true" label="Enter a number" />
<aura:if isTrue="{! false }">
    <lightning:input aura:id="fieldId" type="number" name="input2" required="true" label="Enter another number" />
</aura:if>
<lightning:button variant="brand" label="Check" value="check" onclick="{!c.testMe}"/>

Based on the helpful answer from itzmukeshy7, here is my revised, working controller function:

testMe : function(component) {

    var rows = component.find('fieldId');

    // The following row handles all return types for the find function: 
    // 1. A component
    // 2. An array of components, or 
    // 3. Undefined (no matching components)
    var elements = [].concat(rows || []);

    var allComplete = elements.reduce(function (validSoFar, inputCmp) {
        return validSoFar && !inputCmp.get('v.validity').valueMissing;
    }, true);

    if (allComplete) {
        console.log('All fields complete!');
    } else {
        console.log('Some fields are missing values.');
    }

},
5

This is all fine, there is a trick which is very much hidden in the documentation:

Here is what the documentation says: find documentation

So we can handle this with concat method of array:

var rows = c.find('rowSelector');
var elements = [].concat(rows || []);
/* Now here the elements will always be an array, and won't break your code anymore. */
  • +1 Love this solution, even shorter than what I was using previously. – sfdcfox Mar 14 at 14:25
  • Many thanks! Here is my updated controller function, which works. testMe : function(component) { var rows = component.find('fieldId'); var elements = [].concat(rows || []); var allComplete = elements.reduce(function (validSoFar, inputCmp) { return validSoFar && !inputCmp.get('v.validity').valueMissing; }, true); if (allComplete) { console.log('All fields complete!'); } else { console.log('Some fields are missing values.'); } }, – Matthew Souther Mar 14 at 14:45
  • Great, if it worked for you. – itzmukeshy7 Mar 14 at 14:47
1

When running your example, I'm getting an error saying reduce is not a valid function. You can enable debug mode for lightning components to get these errors.enter image description here

The reason for this is your component.find(...) method. Component.find has two return types. Either an Object or Object[].

In the first example you have multiple instances of a component with id "fieldId". Thus the return type will be a list of aura components.

In the second example there is only one aura component as the other one is conditionally rendered. Hence only one component with id "fieldId" is found. Component.find will return a single object and not a array of objects.

You can resolve the issue by first checking if the result of component.find is an array. If not then add it to an array and apply the same reduce method for simplicity sake.

  • 2
    Actually, component.find(...) returns three types of value, not two: 1. An array, if we have more than one element with the provided id. 2. An element, if we have a unique element with the provided id. 3. undefined, if we don't have any element with the provided id. – itzmukeshy7 Mar 14 at 13:57
  • Thanks for the pointer to use debug mode for Lightning Components -- I will look into that. – Matthew Souther Mar 14 at 14:52

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.