How can Programmatically Selecting Menu Items in aura:iteration?

When building a menu component in Lightning Aura Components, you may want to highlight or select a menu item not only when the user clicks it, but also programmatically from another event or component. A common approach is to use aura:iteration to render a list of items, such as Opportunities, and assign a unique identifier to each rendered item. A typical attempt might involve dynamically binding aura:id to the record Id, and then using component.find() to locate the item. However, this often does not work as expected.

Here is a scenario: You have a list of opportunities displayed in a sub-menu using aura:iteration. When a user clicks a menu item, it highlights correctly using event.currentTarget.id. However, when trying to select the item programmatically from another component via an application event, using component.find(oppId) does not work.

Initial Markup Example (works with click event only):

<aura:iteration items="{!v.opportunities}" var="opp">
    <li class="slds-dropdown__item" role="presentation">
        <a href="javascript:void(0);" role="menuitem" tabindex="-1" id="{!opp.Id}" onclick="{!c.openItemFromMenu}">
            <span class="slds-truncate" title="{!opp.Name}">{!opp.Name}</span>
        </a>
    </li>
</aura:iteration>

Controller Example (click handler):

openItemFromMenu: function(component, event, helper) {
    var oppId = event.currentTarget.id;
    var selectedItemNew = component.find(oppId);
    selectedItemNew.style = "background: rgb(216, 237, 255);";
}

This works fine because the id attribute of the HTML element is accessible via event.currentTarget.id during a click event. But the problem arises when you try to select the item programmatically using an Aura event:

<aura:handler name="eventSelectMenuItem" event="c:myEvent" action="{!c.openItemFromMenu}" />
<a href="javascript:void(0);" role="menuitem" tabindex="-1" id="{!opp.Id}" onclick="{!c.openItemFromMenu}" aura:id="{!opp.Id}">

And in the controller:

openItemFromMenu: function(component, event, helper) {
    var oppId = event.getParam("recordId");
    var selectedItemNew = component.find(oppId); // Does not work
    selectedItemNew.style = "background: rgb(216, 237, 255);";
}

The issue here is that component.find() does not support dynamic expressions in aura:id. aura:id must be static, which is why component.find(oppId) cannot locate the item programmatically.

Correct Approach Using Static aura:id

Instead of binding aura:id to a dynamic value, assign a static aura:id to all items in the iteration, such as "link":

<aura:iteration items="{!v.opportunities}" var="opp">
    <li class="slds-dropdown__item" role="presentation">
        <a href="javascript:void(0);" role="menuitem" tabindex="-1" id="{!opp.Id}" onclick="{!c.openItemFromMenu}" aura:id="link">
            <span class="slds-truncate" title="{!opp.Name}">{!opp.Name}</span>
        </a>
    </li>
</aura:iteration>

In the controller, you can use component.find('link').getElements() to get an array of all the rendered elements and then search for the specific item by its HTML id:

openItemFromMenu: function(component, event, helper) {
    var oppId = event.getParam("recordId");
    var selectedItemsNew = component.find('link').getElements();

    if (Array.isArray(selectedItemsNew)) {
        var selectedItemNew = selectedItemsNew.find(function(oneItem) {
            return oppId === oneItem.id;
        });
        if (selectedItemNew) {
            selectedItemNew.style.background = "rgb(216, 237, 255)";
        }
    } else if (selectedItemsNew) {
        if (oppId === selectedItemsNew.id) {
            selectedItemsNew.style.background = "rgb(216, 237, 255)";
        }
    }
}

Why This Works

When you assign a static aura:id to all items in the iteration, component.find('link') returns all the components with that aura:id as an array. This allows you to loop through them and compare their HTML id (which is still unique for each opportunity) to find the exact one you want to highlight.

Using HTML id ensures each element can still be uniquely identified, while aura:id allows you to retrieve the rendered components programmatically. This method works for both user click events and programmatic selection triggered by Aura events.

Best Practices

Instead of directly modifying the style property, a better approach is to define a CSS class for the selected state:

.selectedMenuItem {
    background-color: rgb(216, 237, 255);
}

Then, in the controller, toggle the class dynamically:

$A.util.addClass(selectedItemNew, 'selectedMenuItem');

This keeps styling centralized in CSS, makes your component easier to maintain, and ensures consistent behavior if you want to change styles later.

Kick Start Your Journey with Real-Time Project-Based Salesforce Learning

Our Salesforce Course is designed to offer a complete understanding of the Salesforce platform, providing you with the necessary skills to excel in the CRM industry. The program covers essential modules such as Salesforce Admin, Developer, and AI, combining theoretical knowledge with practical experience. Through real-world projects and assignments, you’ll develop the expertise needed to solve complex business challenges using Salesforce solutions. Our expert instructors ensure you gain both technical skills and valuable industry insights to succeed in the Salesforce environment.

Along with technical expertise, our Salesforce training in Chennai offers personalized mentoring, certification preparation, and interview coaching to improve your career prospects. You’ll have access to comprehensive study resources, practical project experience, and continuous support throughout your learning journey. By the time you complete the course, you’ll be well-equipped for certification exams and capable of applying your problem-solving skills in real-world scenarios. Begin your Salesforce career with us and unlock limitless career opportunities. Enroll for a Free Demo today!

0
Would love your thoughts, please comment.x
()
x