0% found this document useful (0 votes)
11 views7 pages

LWC Iterators: for:each vs iterator Guide

Uploaded by

eashwarguru
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views7 pages

LWC Iterators: for:each vs iterator Guide

Uploaded by

eashwarguru
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Lightning Web Components: Iterators (for:each

& iterator) — Deep Dive + Real Interview Q&A

1) Why Iterators Matter in LWC


Rendering lists is a core UI requirement in Salesforce apps — from Opportunities on an
Account to Line Items in a Quote. LWC provides two main ways to loop over collections in
templates: the simple and fast 'for:each' and the more powerful 'iterator' directive which
exposes first/last and surrounding items for advanced UIs.

 for:each → lightweight, most common; iterate arrays quickly.


 iterator → exposes special properties (first, last, index, previous, next) for context-
aware rendering.
 Both require a stable 'key' for efficient DOM diffing and re-rendering.

2) for:each vs iterator — Key Differences


 API: for:each={array} for:item='item' for:index='index' vs iterator:it={array}
 Context: 'for:each' gives you 'item' and optional 'index'; 'iterator' gives '[Link]', '[Link]',
'[Link]', '[Link]', '[Link]', '[Link]'.
 Use-cases: 'for:each' for simple lists; 'iterator' when you need separators, grouping
headers, drag handles, first/last badges, or to compare neighboring records.
 Performance: Both are virtual-DOM friendly; correctness of 'key' impacts re-render cost
more than choice of directive.

3) Syntax Cheatsheet
3.1) for:each basic

<template for:each={contacts} for:item="con" for:index="i">


<p key={[Link]}>{i + 1}. {[Link]} — {[Link]}</p>
</template>

3.2) iterator for advanced rendering

<template iterator:it={contacts}>
<div key={[Link]}>
<template if:true={[Link]}>
<h3>Team Contacts</h3>
</template>
<p>{[Link] + 1}. {[Link]}</p>

<template if:false={[Link]}>
<hr/>
</template>
</div>
</template>

4) Real-Life Scenario: Quote Line Items with Subtotals


Business ask: In a Quote screen, show line items grouped by Product Family with a
subtotal after each family, and a grand total at the end. We also need a subtle divider
between items, except after the last item in a group.

Controller (Apex — wireable)

public with sharing class QuoteItemsController


{ @AuraEnabled(cacheable=true)
public static List<QuoteLineItem> fetchItems(Id quoteId) {
return [SELECT Id, Quantity, UnitPrice, TotalPrice, [Link],
[Link]
FROM QuoteLineItem WHERE QuoteId = :quoteId ORDER BY
[Link], [Link]];
}
}

LWC JS

import { LightningElement, wire, api } from 'lwc';


import fetchItems from '@salesforce/apex/[Link]';

export default class QuoteItems extends LightningElement


{ @api recordId;
items = [];
grouped = [];
total = 0;

@wire(fetchItems, { quoteId: '$recordId' })


wired({ data, error }) {
if (data) {
[Link] = [Link]((x) =>
({ id: [Link],
name: [Link],
family: [Link],
qty: [Link],
price: [Link],
total: [Link]
}));
// group by family
const m = new Map();
for (const it of [Link]) {
if (![Link]([Link])) [Link]([Link], []);
[Link]([Link]).push(it);
}
[Link] = [Link]([Link]()).map(([family, rows]) =>
({ family, rows, subtotal: [Link]((s, r) => s + [Link], 0)
}));
[Link] = [Link]((s, g) => s + [Link], 0);
} else if (error) {
// handle error
// eslint-disable-next-line no-console
[Link](error);
}
}
}

LWC HTML using iterator

<template>
<template for:each={grouped} for:item="grp">
<section key={[Link]} class="family">
<h3>{[Link]}</h3>
<template iterator:it={[Link]}>
<div key={[Link]} class="row">
<span>{[Link]}</span>
<span>{[Link]} × {[Link]}</span>
<span>= {[Link]}</span>
</div>
<template if:false={[Link]}>
<div class="divider"></div>
</template>
</template>
<p class="subtotal">Subtotal: {[Link]}</p>
</section>
</template>

<h2>Grand Total: {total}</h2>


</template>
5) Best Practices
 Always provide a stable key (record Id or deterministic composite key).
 Avoid using array index as key when the array can reorder; it causes incorrect re-use of
DOM nodes.
 Pre-compute data in JS (grouping, totals) to keep templates clean and fast.
 Use iterator when you need first/last or to compare neighbors; otherwise default to
for:each for readability.
 Guard against null/undefined arrays before rendering to prevent template errors.
 When mutating arrays, create new arrays (spread [...arr]) to trigger reactivity.

6) Real Interview Q&A

Q1. What they asked me: What's the difference between 'for:each' and 'iterator' in
LWC?
Ans: for:each is a lightweight loop that exposes each item and optional index. iterator
wraps each item as an object exposing 'value', 'first', 'last', 'index', and neighbors. I use
iterator when the UI depends on boundaries (first/last) or needs separators/group
headers.

Tips:

Start with a one-liner difference, then give 1–2 concrete use-cases like adding <hr> between
items or group subtotals.

Q2. What they asked me: When would you prefer 'iterator' over 'for:each'?

Ans: Whenever I need context of the current item's position — e.g., show a header before
the first item, hide a divider after the last, compare with previous to decide if a new
date/group starts.

Tips:

Mention 'first' and 'last' explicitly; interviewers expect those keywords.

Q3. What they asked me: Why is 'key' mandatory and how do you choose it?

Ans: The key allows LWC’s diffing algorithm to map data items to DOM nodes across
renders, preventing flicker and preserving component state. I pick a stable unique Id (e.g.,
record Id). I avoid array indexes if the order can change.

Tips:
Add a quick pitfall: using index as key breaks when array mutates.

Q4. What they asked me: How do you render a separator between items except the
last one?

Ans: Use iterator and wrap the separator in <template if:false={[Link]}>. That way the last
item won’t render a trailing line.

Tips:

If asked to code, write 3–4 lines of template showing [Link].

Q5. What they asked me: How can you show a 'No records' message safely?

Ans: Guard with conditional template: <template


if:true={[Link]}>...list...</template><template if:false={[Link]}>No
records</template> and default records to [].

Tips:

Mention initializing arrays to [] to avoid undefined errors.

Q6. Explain how you'd implement alternating row backgrounds (zebra rows).

Ans: Use the index (for:each with for:index or iterator's [Link]) and compute a class:
class={[Link] % 2 ? 'odd' : 'even'}.

Tips:

Call out that index is fine for CSS decisions but not as a DOM key.

Q7. What they asked me: How do you group records and show subtotals per group?

Ans: Compute groups in JS (Map by key), render outer for:each over groups, then inner
iterator over rows to place separators and subtotals.

Tips:

Stress separation of concerns: complex logic → JS, simple loop → HTML.


Q8. What they asked me: What happens if you forget 'key' on a looped element?

Ans: LWC will throw a compilation error because a keyed element is required for list
rendering to ensure deterministic diffing.

Tips:

Add that the key must be on the topmost repeated element inside the loop.

Q9. Can you access previous item’s value inside 'for:each'?

Ans: Not directly. 'for:each' only gives item/index. To access neighbors in template, switch
to 'iterator' which gives '[Link]' and '[Link]' or compute needed flags in JS.

Tips:

Offer both routes: iterator or precompute flags in JS.

Q10. What they asked me: How do you re-render after pushing to an array?

Ans: Assign a new array reference: [Link] = [...[Link], newItem]; to trigger reactivity.

Tips:

Also mention immutability for predictable updates.

Q11. What they asked me: Show code to render contacts and add a header only once
before the first row.

Ans: Use iterator: <template iterator:it={contacts}><template


if:true={[Link]}><h3>Contacts</h3></template><p
key={[Link]}>{[Link]}</p></template>.

Tips:

Keep it minimal; interviewers evaluate clarity.

Q12. What they asked me: How to handle very large lists efficiently?

Ans: Paginate or virtualize; don’t render thousands at once. Use server-side paging or
lightning-datatable with pagination, and only render what’s visible.
Tips:

Tie back to governor limits indirectly: server round-trips with cacheable Apex.

7) Common Pitfalls with Examples

<!-- BAD: Using index as key (order can change) -->


<template for:each={rows} for:item="r" for:index="i">
<div key={i}>{[Link]}</div>
</template>

<!-- GOOD: Use stable Id -->


<template for:each={rows} for:item="r">
<div key={[Link]}>{[Link]}</div>
</template>

8) Quick Checklist Before You Ship


 Do I really need iterator? (Only if first/last/neighbor logic is required)
 Are my keys stable and unique?
 Is business logic in JS and UI kept simple?
 Do I handle empty/errored states gracefully?
 Have I tested reactivity after array mutations?

9) Copy-Paste Snippets

<!-- Separator except last -->


<template iterator:it={rows}>
<div key={[Link]}>{[Link]}</div>
<template if:false={[Link]}><hr/></template>
</template>

<!-- Header on first only -->


<template iterator:it={rows}>
<template if:true={[Link]}><h3>Header</h3></template>
<div key={[Link]}>{[Link]}</div>
</template>

You might also like