Use document.getElementById for elements that load from server data

Itai Shmida 08/07/2018. 1 answers, 71 views
lightning-components lightning aura-iteration lightning-renderer

I use document.getElementById with the id attribute to locate elements in my component. I cannot use component.find and aura:id because the elements are generated from an iteration.

This iteration is over a list of records that I get from the server.

PROBLEM

document.getElementById cannot find the elements because they are not rendered yet - they will be rendered only after the server returns the records.

CURRENT SOLUTION

I have put the document.getElementById inside the aura:handler name="change" event, and also then I use a waiting mechanism to check if the element exist:

MARKUP

<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

<aura:handler name="change" value="{!v.records}" action="{!c.recordsFinishedLoading}"/>
<aura:attribute name="maxSelectionsTry" type="Integer" default="5" />

<aura:attribute name="records" type="sObject[]" description="list of records" />

<nav class="slds-context-bar__secondary" role="navigation">
    <ul class="slds-grid">  
        <li class="slds-context-bar__item">
            <a href="javascript:void(0);" class="slds-context-bar__label-action" title="labelAccount}" onclick="{!c.openAccount}">
                <span class="slds-truncate" title="labelAccount">labelAccount</span>
            </a>
        </li>
        <li class="slds-context-bar__item slds-context-bar__dropdown-trigger slds-dropdown-trigger slds-dropdown-trigger_hover">
            <a href="javascript:void(0);" class="slds-context-bar__label-action" title="labelRecords}" onclick="{!c.openRecords}">
                <span class="slds-truncate" title="labelRecords">labelRecords</span>
            </a>
            <div class="slds-context-bar__icon-action slds-p-left_none">
                <lightning:icon iconName="utility:chevrondown" size="x-small" alternativeText="Open Submenu"/>
            </div>
            <div class="slds-dropdown">
                <ul class="slds-dropdown__list" role="menu">

                    <aura:if isTrue="{! and(v.records, v.records.length>0)}">
                        <!--iterate on all records-->
                        <aura:iteration items="{!v.records}" var="record">
                            <li class="slds-dropdown__item" role="presentation">
                                <a href="javascript:void(0);" role="menuitem" tabindex="-1" id="{!record.Id}" onclick="{!c.openRecordFromMenu}">
                                    <span class="slds-truncate" title="{!record.Name}">{!record.Name}</span>
                                </a>
                            </li>
                        </aura:iteration>
                    </aura:if>
                </ul>
            </div>
        </li>
    </ul>
</nav>

CONTROLLER

recordsFinishedLoading: function(component, event, helper) {
    var recordId = "someHardCodedID";
    helper.findId(component, helper, recordId)
}

HELPER

findId: function(component, helper, recordId) {
    var itemById = document.getElementById(recordId);
    if (itemById) {
        // do some css stuff on this item
    }
    else {
        // element does not exist yet - so sleep and retry (for maxSelectionsTry times)
        var maxSelectionsTry = component.get("v.maxSelectionsTry");
        if (maxSelectionsTry > 0){
            component.set("v.maxSelectionsTry", maxSelectionsTry-1);
            setTimeout(function() {
                helper.findId(component, helper, grantId);
            }, 1000 /*1second*/);
        }
    }
},

I have tried to use document.getElementById from aura:handler name="change" but it returns null.

I have tried to use document.getElementById from the custom afterRender but it returns null.

QUESTION

Is there any other way to wait for the page to load and then document.getElementById would work?

Is there a nicer way to overcome this problem?

1 Answers


Itai Shmida 08/09/2018.

Quick answer: There is no way to decide when the elements are rendered already, and then to query and use document.getElementById - the way I posted in the question - to sleep in a loop, is an ugly, but working, way to do that.

I had a solution to my problem by the help of @sfdcfox, and what I did is - adding the css name to the records after they returned from server, while in the markup I am binding the className to it:

MARKUP CHANGES:

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

CONTROLLER CHANGES IN THE METHOD

getRecords: function(component, event, helper) {
    helper.getRecords(component, helper);
},

HELPER CHANGES IN THE METHOD - mainly adding the addSelectedRecordClass method after data was received:

getRecords: function(component, helper){
    // get records from server - a list of sObjects
    var action = component.get("c.getRecords");
    action.setParams({
        sObjectName: 'Contact',
        commaDelimitedFieldNames: 'Id,Name'
    });
    action.setCallback(this, function(response){
        var state = response.getState();
        if (component.isValid() && state === "SUCCESS") {
            var records = response.getReturnValue();
            records = helper.addSelectedRecordClass(component, records);
            component.set("v.records", records);
        }
    });
    $A.enqueueAction(action);
},

// find the selected record in the given record list, and add a css class to highlight it
addSelectedRecordClass: function(component, records) {
    var selectedRecordId = component.get("v.selectedRecord");
    for(var i=0; i<records.length; i++) {
        if (records[i].Id == selectedRecordId)
            records[i].className = 'selectedMenuItem';
        else
            records[i].className = '';
    }
    return records;
},

HighResolutionMusic.com - Download Hi-Res Songs

1 The Chainsmokers

Beach House flac

The Chainsmokers. 2018. Writer: Andrew Taggart.
2 (G)I-DLE

POP/STARS flac

(G)I-DLE. 2018. Writer: Riot Music Team;Harloe.
3 Ariana Grande

​Thank U, Next flac

Ariana Grande. 2018. Writer: Crazy Mike;Scootie;Victoria Monét;Tayla Parx;TBHits;Ariana Grande.
4 Anne-Marie

Rewrite The Stars flac

Anne-Marie. 2018. Writer: Benj Pasek;Justin Paul.
5 Clean Bandit

Baby flac

Clean Bandit. 2018. Writer: Jack Patterson;Kamille;Jason Evigan;Matthew Knott;Marina;Luis Fonsi.
6 Nicki Minaj

No Candle No Light flac

Nicki Minaj. 2018. Writer: Denisia “Blu June” Andrews;Kathryn Ostenberg;Brittany "Chi" Coney;Brian Lee;TJ Routon;Tushar Apte;ZAYN;Nicki Minaj.
7 BlackPink

Kiss And Make Up flac

BlackPink. 2018. Writer: Soke;Kny Factory;Billboard;Chelcee Grimes;Teddy Park;Marc Vincent;Dua Lipa.
8 Imagine Dragons

Bad Liar flac

Imagine Dragons. 2018. Writer: Jorgen Odegard;Daniel Platzman;Ben McKee;Wayne Sermon;Aja Volkman;Dan Reynolds.
9 BTS

Waste It On Me flac

BTS. 2018. Writer: Steve Aoki;Jeff Halavacs;Ryan Ogren;Michael Gazzo;Nate Cyphert;Sean Foreman;RM.
10 Halsey

Without Me flac

Halsey. 2018. Writer: Halsey;Delacey;Louis Bell;Amy Allen;Justin Timberlake;Timbaland;Scott Storch.
11 Little Mix

Woman Like Me flac

Little Mix. 2018. Writer: Nicki Minaj;Steve Mac;Ed Sheeran;Jess Glynne.
12 Brooks

Limbo flac

Brooks. 2018.
13 Fitz And The Tantrums

HandClap flac

Fitz And The Tantrums. 2017. Writer: Fitz And The Tantrums;Eric Frederic;Sam Hollander.
14 Backstreet Boys

Chances flac

Backstreet Boys. 2018.
15 Lady Gaga

I'll Never Love Again flac

Lady Gaga. 2018. Writer: Benjamin Rice;Lady Gaga.
16 Diplo

Close To Me flac

Diplo. 2018. Writer: Ellie Goulding;Savan Kotecha;Peter Svensson;Ilya;Swae Lee;Diplo.
17 Rita Ora

Velvet Rope flac

Rita Ora. 2018.
18 Bradley Cooper

Always Remember Us This Way flac

Bradley Cooper. 2018. Writer: Lady Gaga;Dave Cobb.
19 Imagine Dragons

Machine flac

Imagine Dragons. 2018. Writer: Wayne Sermon;Daniel Platzman;Dan Reynolds;Ben McKee;Alex Da Kid.
20 Erika Sirola

Speechless flac

Erika Sirola. 2018. Writer: Teemu Brunila;Stefan Dabruck;Jürgen Dohr;Guido Kramer;Dennis Bierbrodt;Chris Braide;Robin Schulz.

Related questions

Hot questions

Language

Popular Tags