pick() — Element Selection & Manipulation

pick() selects a single element from the loaded template by selector and returns a CandidElement instance for chaining manipulations. All changes are deferred — they are applied to the DOM only at render time.

---

1. Supported Selectors

Type Example Matches
ID #nav_home <a id="nav_home">
Class .nav-link <a class="nav-link">
Attribute [data-id] <div data-id="1">
Attribute Value [data-id=123] <div data-id="123">
Tag + Class a.nav-link <a class="nav-link">
Simple (Legacy) nav_home id, name, or tag match
❌ Combinators not supported: div > a, div a
❌ Pseudo selectors not supported: li:first-child
❌ Tag + ID not supported: div#main
❌ Tag + Attribute not supported: a[href]
---

2. Content Manipulation

Set inner content

// Plain text
$tpl->pick('title')->content('Welcome to our site');

// HTML content
$tpl->pick('description')->content('<strong>Breaking:</strong> Latest news');

// Dynamic value
$tpl->pick('#pageTitle')->content($page->title);
Replace element entirely

// Replaces the element itself — not just its content
$tpl->pick('breadcrumb')->replace('<nav>Home › News</nav>');
Prefix and suffix content

$tpl->pick('#counter')->prefixContent('Total: ');
$tpl->pick('#counter')->suffixContent(' items');

// Result: Total: 42 items
---

3. Attribute Manipulation

Set attribute

$tpl->pick('nav_home')->attribute('class', 'nav-item nav-link active');
$tpl->pick('.hero-img')->attribute('src', '/img/hero.jpg');
$tpl->pick('#searchInput')->attribute('placeholder', 'Search news...');
Prefix and suffix attribute

// Add base URL prefix to existing src
$tpl->pick('.logo')->prefixAttribute('src', 'https://cdn.example.com');

// Append query string to existing href
$tpl->pick('#pageLink')->suffixAttribute('href', '?ref=home');
Data and Aria attributes

$tpl->pick('#modal')->data('id', $item->id);
$tpl->pick('#modal')->data('type', 'confirm');
$tpl->pick('#menuBtn')->aria('expanded', 'false');
$tpl->pick('#menuBtn')->aria('label', 'Toggle menu');

// Renders as:
// data-id="1" data-type="confirm"
// aria-expanded="false" aria-label="Toggle menu"
Common shorthands

$tpl->pick('.logo')->src('/img/logo.png');
$tpl->pick('#backLink')->href('/news');
$tpl->pick('#emailInput')->value($user->email);
$tpl->pick('#emailInput')->placeholder('Enter your email');
---

4. Class Manipulation


// Add class
$tpl->pick('#nav_home')->addClass('active');

// Remove class
$tpl->pick('#nav_home')->removeClass('active');

// Toggle class based on condition
$tpl->pick('#nav_home')->toggleClass('active', $currentPage === 'home');

// Check if class exists (read — not deferred)
if ($tpl->pick('#nav_home')->hasClass('active')) {
    // ...
}

// Active state shorthand
$tpl->pick('#nav_home')->activeIf($currentPage === 'home');
$tpl->pick('#nav_about')->activeIf($currentPage === 'about');
---

5. Visibility


// Remove element from DOM if false
$tpl->pick('.admin-panel')->showIf($user->isAdmin());

// Remove element from DOM if true
$tpl->pick('.guest-banner')->hideIf($user->isLoggedIn());

// For entire sections — prefer slotIf() over showIf()
// showIf: template is loaded, element removed at render
// slotIf: template never loads at all
---

6. Form Element Helpers


// Checked state
$tpl->pick('#rememberMe')->checkedIf($user->prefersRemembered());

// Disabled state
$tpl->pick('#submitBtn')->disabledIf($form->isProcessing());

// Required
$tpl->pick('#email')->requiredIf($form->emailIsRequired());

// Readonly
$tpl->pick('#username')->readonlyIf(!$user->canEditUsername());

// Selected (for option elements)
$tpl->pick('#optionYes')->selectedIf($answer === 'yes');
---

7. Reading Values

These read directly from the DOM — not from pending assignments. Use before making assignments for accurate values.


// Get text content
$title = $tpl->pick('#pageTitle')->getContent();
$title = $tpl->pick('#pageTitle')->getContent('Default Title'); // with fallback

// Get attribute value
$src = $tpl->pick('.logo')->getAttribute('src');
$src = $tpl->pick('.logo')->getAttribute('src', '/img/default.png'); // with fallback

// Check element exists
if ($tpl->pick('#optionalBanner')->exists()) {
    $tpl->pick('#optionalBanner')->content($banner->text);
}
---

8. Chaining

Most methods return self — chain freely:


$tpl->pick('#submitBtn')
    ->content('Submit Form')
    ->attribute('type', 'submit')
    ->addClass('btn-primary')
    ->disabledIf($form->isProcessing())
    ->data('form-id', $form->id)
    ->aria('label', 'Submit the form');

$tpl->pick('nav_home')
    ->href('/news')
    ->content('Home')
    ->activeIf($currentPage === 'home')
    ->aria('current', 'page');
---

9. Multiple Elements — pickAll()

Use pickAll() to select and manipulate all matching elements at once. Returns a CandidElements collection.


// Apply to all matching elements
$tpl->pickAll('.nav-link')->each(function(CandidElement $el, int $index) {
    $el->activeIf($index === $currentIndex);
});

// Bulk operations
$tpl->pickAll('.card-img')
    ->addClass('img-fluid')
    ->attribute('loading', 'lazy');

// First and last
$tpl->pickAll('.nav-link')->first()->addClass('first-link');
$tpl->pickAll('.nav-link')->last()->addClass('last-link');

// Filter then manipulate
$tpl->pickAll('.nav-link')
    ->filter(fn(CandidElement $el) => $el->hasClass('external'))
    ->attribute('target', '_blank')
    ->attribute('rel', 'noopener noreferrer');

// Count
$count = $tpl->pickAll('.nav-link')->count();
---

10. Deferred Execution

Important: All pick() manipulations are deferred. They are queued and applied to the DOM only when render() is called. Reading methods (getContent(), getAttribute(), exists(), hasClass()) read from the current DOM state — use them before making assignments for accurate results.

// ✅ Read first, then write
$existing = $tpl->pick('#title')->getContent();
$tpl->pick('#title')->content($existing . ' — Updated');

// ⚠️ Writing then reading returns original DOM value
$tpl->pick('#title')->content('New Title');
$val = $tpl->pick('#title')->getContent(); // still returns original
---

11. Common Mistakes

❌ Using combinator selectors: pick('div > a') — not supported

❌ Reading after writing and expecting updated value

❌ Using showIf() for large sections — use slotIf() instead

❌ Calling pick() on a selector that matches multiple elements — use pickAll() instead
---

12. Quick Reference

Method Purpose Deferred
content(value)Set inner HTML/text✅
replace(value)Replace element itself✅
prefixContent(text)Prepend to content✅
suffixContent(text)Append to content✅
attribute(name, value)Set attribute✅
prefixAttribute(name, text)Prepend to attribute✅
suffixAttribute(name, text)Append to attribute✅
href(url)Set href✅
src(url)Set src✅
value(val)Set value✅
placeholder(text)Set placeholder✅
data(key, value)Set data-* attribute✅
aria(key, value)Set aria-* attribute✅
addClass(class)Add CSS class✅
removeClass(class)Remove CSS class✅
toggleClass(class, bool)Conditional class✅
activeIf(bool)Toggle active class✅
showIf(bool)Remove if false✅
hideIf(bool)Remove if true✅
checkedIf(bool)Set checked✅
disabledIf(bool)Set disabled✅
requiredIf(bool)Set required✅
readonlyIf(bool)Set readonly✅
selectedIf(bool)Set selected✅
getContent(default)Read text content❌
getAttribute(name, default)Read attribute❌
exists()Check element found❌
hasClass(class)Check class exists❌
---
pick() is the primary way to bind data to your templates. Chain methods freely — all writes are deferred until render() keeping your template logic clean and readable.