Targeting Elements by ID
Elements.update() targets elements by their id attributes. Understanding why IDs are the right tool for named-element updates — and how to use them well — will make your code cleaner and more maintainable.
Quick Start (30 Seconds)
// Good IDs: descriptive, camelCase, consistent
Elements.update({
loginFormTitle: { textContent: 'Sign in to your account' },
emailInputField: { disabled: false, value: '' },
submitLoginBtn: { disabled: false, textContent: 'Sign In' },
loginErrorMsg: { style: { display: 'none' } }
});Readable, self-documenting, and immediately clear what each line does.
What Is an ID?
An HTML id attribute is a unique identifier for one specific element on the page. Think of it like a badge number — unique, permanent, tied to that one element.
<h1 id="pageTitle">Welcome</h1>
<button id="submitBtn">Submit</button>
<div id="userProfile">...</div>No two elements on the same page should share an ID.
Syntax
// The key in Elements.update() must match the id attribute exactly
Elements.update({
myElementId: { /* update object */ }
//^^^^^^^^^
// Must match: <element id="myElementId">
});Why IDs Are Perfect for Elements.update()
They're Specific
An ID targets exactly one element — no ambiguity, no accidental matches:
Elements.update({
submitBtn: { disabled: false } // One specific button
});They're Self-Documenting
Well-chosen IDs describe what the element is, making update code readable without comments:
Elements.update({
loginFormError: { textContent: 'Invalid credentials' },
passwordStrength: { textContent: 'Strong' },
submitLoginBtn: { disabled: false }
});
// Reads clearly: update login error, password strength, and submit buttonThey're Fast
Browsers maintain an internal index of IDs — getElementById is the fastest DOM lookup available. Elements.update() uses this for efficient resolution.
Why Does This Exist?
When Single-Element Updates Are Your Priority
Direct single-element updates are great for one element at a time:
Elements.submitBtn.update({ disabled: true });This approach is great when you need: ✅ Maximum brevity for one targeted change ✅ No need to verify multiple elements at once
When Bulk Named-Element Updates Are Your Goal
In scenarios where multiple specific elements change together as one action, the bulk form provides a unified, verifiable approach:
Elements.update({
emailInput: { disabled: true },
passwordInput: { disabled: true },
submitBtn: { disabled: true, textContent: 'Signing in...' },
errorMsg: { style: { display: 'none' } }
});This is especially useful when: ✅ 2+ elements change as part of one conceptual action ✅ You want to see the complete state change in one block ✅ You need a results receipt to verify all elements were found ✅ You're managing forms, dashboards, or modals with named slots
The Choice Is Yours:
- Use
Elements.myId.update({})for single elements - Use
Elements.update({})for multiple named elements together
Mental Model: The Postal Address System
Think of IDs like postal addresses. Each address uniquely identifies exactly one location:
id="loginFormTitle" → The login form's title heading (one specific element)
id="submitLoginBtn" → The login form's submit button (one specific element)
id="loginErrorMsg" → The login form's error display (one specific element)Elements.update() is like sending update packages to specific named addresses. Each address gets its own package with its own contents.
How Does It Work?
Elements.update({ submitBtn: {...}, errorMsg: {...} })
│
For "submitBtn":
document.getElementById("submitBtn")
├─→ Found → apply update → record success
└─→ Not found → record failure (app continues)
│
For "errorMsg":
document.getElementById("errorMsg")
├─→ Found → apply update → record success
└─→ Not found → record failure (app continues)ID Naming Best Practices
Use camelCase
JavaScript convention for identifiers is camelCase — and since IDs become JavaScript-accessible keys, camelCase is the standard:
// ✅ Good — camelCase
Elements.update({
userProfile: { /* ... */ },
submitFormBtn: { /* ... */ },
loginErrorMessage: { /* ... */ }
});Be Descriptive About Purpose
IDs should describe what the element is (its role), not what it looks like:
<!-- ✅ Good — purpose-based -->
<button id="loginBtn">Login</button>
<div id="userProfileCard">...</div>
<!-- ❌ Bad — appearance-based -->
<button id="blueButton">Login</button>
<div id="topLeftBox">...</div>Appearance changes. Purpose doesn't. loginBtn will always make sense. blueButton breaks the moment you redesign.
Use Consistent Naming Patterns
Choose a pattern and stick to it:
<!-- Pattern: [context][ElementType] -->
<input id="emailInput" />
<input id="passwordInput" />
<button id="submitBtn" />
<div id="errorMsg" />
<!-- Pattern: [page][Component] for multi-page apps -->
<input id="loginEmailInput" />
<button id="loginSubmitBtn" />
<input id="registerEmailInput" />
<button id="registerSubmitBtn" />Common ID Patterns
Component-Based IDs
<div id="loginForm">
<input id="loginEmailInput" type="email" />
<input id="loginPasswordInput" type="password" />
<button id="loginSubmitBtn">Sign In</button>
<div id="loginErrorMsg"></div>
</div>Elements.update({
loginEmailInput: { value: '', disabled: false },
loginPasswordInput: { value: '', disabled: false },
loginSubmitBtn: { disabled: false, textContent: 'Sign In' },
loginErrorMsg: { style: { display: 'none' } }
});State Indicator IDs
<div id="loadingSpinner" style="display: none;">Loading...</div>
<div id="successBanner" style="display: none;">Success!</div>
<div id="errorBanner" style="display: none;">Error occurred</div>// Show loading — hide others
Elements.update({
loadingSpinner: { style: { display: 'flex' } },
successBanner: { style: { display: 'none' } },
errorBanner: { style: { display: 'none' } }
});
// Show success — hide loading
Elements.update({
loadingSpinner: { style: { display: 'none' } },
successBanner: { style: { display: 'block' } },
errorBanner: { style: { display: 'none' } }
});Dashboard Slot IDs
<span id="totalUsersCount">--</span>
<span id="totalRevenueAmount">--</span>
<span id="activeSessionsCount">--</span>
<span id="lastUpdatedTime">Never</span>Elements.update({
totalUsersCount: { textContent: metrics.users.toLocaleString() },
totalRevenueAmount: { textContent: `$${metrics.revenue.toLocaleString()}` },
activeSessionsCount:{ textContent: metrics.activeSessions.toString() },
lastUpdatedTime: { textContent: new Date().toLocaleTimeString() }
});IDs vs Classes vs Selectors
| Approach | Use When | Method |
|---|---|---|
| ID | Specific, uniquely named element | Elements.update() |
| Class | Groups of similar elements | Collections.update() |
| Selector | Complex CSS targeting | Selector.update() |
When NOT to Use IDs
IDs must be unique. Don't use them for repeated elements:
<!-- ❌ Bad — duplicate IDs are invalid HTML -->
<div id="card">Card 1</div>
<div id="card">Card 2</div>
<!-- ✅ Good — use classes for repeated elements -->
<div class="card">Card 1</div>
<div class="card">Card 2</div>For repeated elements, use Collections.update():
Collections.update({
card: { style: { padding: '20px' } } // Updates all .card elements
});Verifying ID Matches
The most common mistake: ID in JavaScript doesn't match id in HTML.
<button id="submitFormBtn">Submit</button>Elements.update({ submitFormBtn: { disabled: true } }); // ✅
Elements.update({ SubmitFormBtn: { disabled: true } }); // ❌ capital S
Elements.update({ submit_form_btn: { disabled: true } }); // ❌ underscore
Elements.update({ submitButton: { disabled: true } }); // ❌ different nameAlways verify with the return value:
const results = Elements.update({ submitFormBtn: { disabled: true } });
if (!results.submitFormBtn.success) {
console.error('submitFormBtn not found — check your HTML id attribute');
}Key Takeaways
- IDs are unique — one ID, one element, no ambiguity
- Use camelCase — consistent with JavaScript naming
- Describe purpose —
loginBtnnotblueButton - Be consistent — choose a naming pattern and stick to it
- Case-sensitive —
submitBtn≠SubmitBtn - IDs for unique elements only — repeated elements use classes +
Collections.update() - Verify with return value — check results when element existence is uncertain
What's Next?
- Chapter 4: Real-world examples — full patterns for common UI scenarios
- Chapter 5: Update object properties — everything you can include
- Chapter 6: The return value — verification and element references