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.