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:
❌ Pseudo selectors not supported:
❌ Tag + ID not supported:
❌ Tag + Attribute 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:
❌ Reading after writing and expecting updated value
❌ Using
❌ Calling
---
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.