PAD + htmx 🛒 0

Active search

The results update as you type. htmx asks the page again with hx-target="#results"; PAD answers the {fragment 'results'} of the same template - the element's name is enough.

{fragment}HX-Target hx-gethx-trigger delayhx-push-url
Live

24 products

ProductCategoryPrice
🎧 Aurora HeadphonesAudio€189.00
ðŸŽķ Pebble EarbudsAudio€79.00
🔊 Boom SpeakerAudio€129.00
🎙ïļ Studio MicrophoneAudio€99.00
ðŸ’ŧ Nimbus Laptop 14Computing€1,299.00
ðŸ–Ĩïļ Atlas Monitor 27Computing€349.00
ðŸ–ąïļ Glide MouseComputing€39.00
âŒĻïļ Tactile KeyboardComputing€119.00
📷 Drift WebcamComputing€69.00
ðŸ’Ą Ember Desk LampHome€59.00
ðŸŦ– Brew KettleHome€49.00
☕ Pour-over SetHome€35.00
🛏ïļ Cloud PillowHome€45.00
ðŸŠī Leaf PlanterHome€25.00
🎒 Trail Backpack 28LOutdoor€139.00
ðŸĨĪ Summit BottleOutdoor€29.00
⛹ Ridge Tent 2POutdoor€279.00
ðŸ”Ķ Beam HeadlampOutdoor€34.00
⌚ Compass WatchOutdoor€219.00
👜 Canvas ToteAccessories€22.00
ðŸ•ķïļ Shade SunglassesAccessories€89.00
ðŸ“ą Snap Phone CaseAccessories€19.00
👛 Fold WalletAccessories€49.00
🔌 Loop ChargerAccessories€29.00
Requests htmx made
    Nothing yet - use the example above, and every request it makes shows here with the part PAD answered.

    How it is built

    PAD, on the server htmx, in the browser

    <div class="toolbar">
      <div class="search">
        <input class="input" type="search" name="q" value="{$q}" placeholder="Search - try lamp, audio or usb" autocomplete="off"
               aria-label="Search the products" hx-get="?examples/search" hx-trigger="input changed delay:250ms, search"
               hx-target="#results" hx-push-url="true" hx-indicator="#searching">
      </div>
      <span id="searching" class="htmx-indicator spinner" aria-hidden="true"></span>
    </div>
    
    <div id="results">
    {fragment 'results'}
      <p class="muted small">{$count} {if $count eq 1}product{else}products{/if}{if $q} for <mark>{$q}</mark>{/if}</p>
      <table class="table">
        <thead><tr><th>Product</th><th>Category</th><th class="num">Price</th></tr></thead>
        <tbody>
          {found}
          <tr><td>{$emoji} {$name}</td><td><span class="badge">{$category}</span></td><td class="num">{$price | currency('EUR')}</td></tr>
          {/found}
        </tbody>
      </table>
      {if $count eq 0}<div class="empty-state"><span class="big">🔎</span>Nothing in the catalogue matches.</div>{/if}
    {/fragment}
    </div>
    <?php
    
      // The products whose name, category or text holds the query. The same PHP serves the page
      // and every answer to htmx: the input's hx-target="#results" sends HX-Target: results,
      // and PAD answers the {fragment 'results'} of search.pad alone. The query stands in the
      // address (hx-push-url), so a reload - or a link - shows the same results whole.
    
      $q = trim ( htmxText ( 'q' ) );
    
      $found = array_values ( array_filter ( htmxData ( 'products' ), fn ( $product ) =>
                 $q === '' or stripos ( $product ['name'] . ' ' . $product ['category'] . ' ' . $product ['blurb'], $q ) !== FALSE ) );
    
      $count = count ( $found );
    
    ?>