Filter a product catalog
Bound input, server-side filtering, and updated results in one Astro component.
View MarkdownQuery on the server. Render in the same component. This example uses a small local catalog so you can run it without a database; replace the filter callback with your own database query when connecting real products.
Try the interaction
Section titled “Try the interaction”Set a maximum price and apply the filter. Try 10 for no results, 50 for two products, or 100 for the full catalog. Negative and empty prices are rejected.
---import { WebForms } from '@astro-utils/forms/forms.js';---<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width" /> <title><slot name="title" /></title> </head> <body> <WebForms> <slot /> </WebForms> </body></html>---import { BButton, BInput, Bind, BindForm } from '@astro-utils/forms/forms.js';import Layout from '../layouts/Layout.astro';import { products } from '../data/products';
const bind = Bind({ maxPrice: 50 });let matches = products.filter(product => product.price <= bind.maxPrice);
function filterProducts() { matches = products.filter(product => product.price <= bind.maxPrice);}---<Layout> <span slot="title">Filter products</span> <BindForm {bind}> <label for="maxPrice">Maximum price ($)</label> <BInput id="maxPrice" name="maxPrice" type="number" min={0} required />
<BButton onClick={filterProducts} whenFormOK>Apply filter</BButton>
<p role="status">{matches.length} products found</p> <ul>{matches.map(product => <li>{product.name} — ${product.price}</li>)}</ul> </BindForm></Layout>import forms from '@astro-utils/forms';
export const onRequest = forms();import { defineConfig } from 'astro/config';import node from '@astrojs/node';import forms from '@astro-utils/forms/dist/integration.js';
export default defineConfig({ output: 'server', adapter: node({ mode: 'standalone' }), integrations: [forms]});// A local catalog keeps this example runnable without a database.// Replace the filter in your server callback with your application's query.export const products = [ { name: 'Notebook', price: 12 }, { name: 'Desk lamp', price: 35 }, { name: 'Headphones', price: 79 }];How it works
Section titled “How it works”Bind restores the submitted budget, BInput validates the field, and BButton runs filterProducts on the server when the form is valid. Astro renders the result count and matching rows together. The embedded preview simulates this interaction locally.
Run it yourself
Section titled “Run it yourself”Follow the Forms setup or copy the configuration, middleware, and shared layout from the file sidebar. Add both the page and catalog files at the paths shown.