Using component.find in Salesforce Lightning Components

When developing Salesforce Lightning Components you very often use the aura:id attribute on components to tag them and component.find to find them again. This works very well and is documented nicely in the documentation (Finding Components by ID). If however you tag a component using aura:id in an iterator you may not know how many resulting components will be on the page. The component.find method may return undefined (if no matching components), a component instance (if a single match was found) or an array of component instances if multiple components with a matching aura:id was found. This is fine but if you want to loop over any found component Javascript may give you a headache as the resulting variable may contain an array or an object instance. Hmmm… You can either using Vanilla Javascript to figure out whether it’s array (or cheat and use $A.util.isArray) and write code for the array case and code for the single instance case — or you can take the short route.

I always take the short route…

Say you had markup like this using an aura:iteration component to loop over a variable containg 0, 1 or many values.

<aura:iteration var="item" items="{!v.items}">
	<lightning:input type="checkbox" label="{!item}" aura:id="mycheckbox" />
</aura:iteration>

Contrast the approach using “isArray”

const cmps = component.find("mycheckbox");
if (!cmps) return;
if ($A.util.isArray(cmps)) {
    cmps.forEach(cmp => {
        // do stuff...
        cmp.set("v.checked", true);
    })
} else {
    // do stuff on the instance
    cmp.set("v.checked", true);
}

…to the approach of simply concatenating into an array… I find this much nicer, cleaner and it avoids the duplication of code between the single instance and array case. If I know there would always be at least one component it could even be done on a single line i.e. loose the undefined check on the second line. Javascript terse-ness heaven!!

const cmps = component.find("mycheckbox");
if (!cmps) return;
[].concat(cmps).forEach(cmp => cmp.set("v.checked", true));