|
10 | 10 | enhancedFormExampleCode,
|
11 | 11 | basicExampleCode,
|
12 | 12 | advancedExampleCode,
|
| 13 | + clientSideOnlyCode, |
13 | 14 | } from "./codeBlocks.js";
|
14 | 15 |
|
15 | 16 | import FilterPanel from "$lib/components/ui/FilterPanel.svelte";
|
| 17 | + import Table from "$lib/components/data-vis/table/Table.svelte"; |
16 | 18 |
|
17 | 19 | // Accept form prop from parent (runes mode)
|
18 | 20 | let { form } = $props();
|
|
35 | 37 | let clientResultsCount = $state("Ready to filter");
|
36 | 38 | let clientFormSubmitted = $state(false);
|
37 | 39 |
|
| 40 | + // Simple client-side only data |
| 41 | + const simpleItems = [ |
| 42 | + { id: 1, name: "Laptop", category: "electronics" }, |
| 43 | + { id: 2, name: "Mouse", category: "electronics" }, |
| 44 | + { id: 3, name: "Coffee Mug", category: "home" }, |
| 45 | + { id: 4, name: "Desk Chair", category: "home" }, |
| 46 | + ]; |
| 47 | +
|
| 48 | + // Metadata for the Table component |
| 49 | + const simpleMetaData = { |
| 50 | + id: { shortLabel: "ID", explainer: "Item ID" }, |
| 51 | + name: { shortLabel: "Name", explainer: "Item name" }, |
| 52 | + category: { shortLabel: "Category", explainer: "Item category" }, |
| 53 | + }; |
| 54 | +
|
| 55 | + // Client-side state |
| 56 | + let filteredItems = $state(simpleItems); |
| 57 | + let selectedCategory = $state("all"); |
| 58 | +
|
| 59 | + // One simple filter function |
| 60 | + function filterItems(category: string) { |
| 61 | + return category === "all" |
| 62 | + ? simpleItems |
| 63 | + : simpleItems.filter((item) => item.category === category); |
| 64 | + } |
| 65 | +
|
| 66 | + // One filter section |
| 67 | + let oneFilterSection = [ |
| 68 | + { |
| 69 | + id: "category", |
| 70 | + type: "radios" as "radios", |
| 71 | + title: "Category", |
| 72 | + ga4Section: "category_filter", |
| 73 | + ga4IndexSection: 1, |
| 74 | + ga4IndexSectionCount: 1, |
| 75 | + name: "category", |
| 76 | + legend: "Select category", |
| 77 | + options: [ |
| 78 | + { value: "all", label: "All items" }, |
| 79 | + { value: "electronics", label: "Electronics" }, |
| 80 | + { value: "home", label: "Home" }, |
| 81 | + ], |
| 82 | + selectedValue: selectedCategory, |
| 83 | + }, |
| 84 | + ]; |
| 85 | +
|
38 | 86 | // Basic filter sections for use in examples
|
39 | 87 | const basicFilterSections = [
|
40 | 88 | {
|
|
277 | 325 | {
|
278 | 326 | id: "5",
|
279 | 327 | heading:
|
280 |
| - "5. Progressive Enhancement with use:enhance to cancel form submission and process client-side, server-side submission as fallback", |
| 328 | + "5. Client-Side Only with use:enhance cancel() - No Server Fallback", |
| 329 | + content: ClientSideOnlyExample, |
| 330 | + }, |
| 331 | + { |
| 332 | + id: "6", |
| 333 | + heading: |
| 334 | + "6. Progressive Enhancement with use:enhance to cancel form submission and process client-side, server-side submission as fallback", |
281 | 335 | content: EnhancedFormExample,
|
282 | 336 | },
|
283 | 337 | ];
|
|
542 | 596 | ></CodeBlock>
|
543 | 597 | {/snippet}
|
544 | 598 |
|
| 599 | +{#snippet ClientSideOnlyExample()} |
| 600 | + <div class="p-5 bg-white"> |
| 601 | + <h3 class="text-xl font-bold mb-4"> |
| 602 | + Client-Side Only with use:enhance cancel() |
| 603 | + </h3> |
| 604 | + <p class="mb-4"> |
| 605 | + This example demonstrates <code>use:enhance</code> with |
| 606 | + <code>cancel()</code> |
| 607 | + to prevent server submission entirely. All processing happens client-side only. |
| 608 | + <strong>No server fallback</strong> - this requires JavaScript to work. |
| 609 | + </p> |
| 610 | + |
| 611 | + <form |
| 612 | + method="POST" |
| 613 | + use:enhance={({ formData, cancel }) => { |
| 614 | + // Cancel server submission - process client-side only |
| 615 | + cancel(); |
| 616 | + |
| 617 | + // Extract form value |
| 618 | + const category = formData.get("category")?.toString() || "all"; |
| 619 | + |
| 620 | + // Update state |
| 621 | + selectedCategory = category; |
| 622 | + filteredItems = filterItems(category); |
| 623 | + |
| 624 | + // No return needed - we cancelled the submission |
| 625 | + }} |
| 626 | + > |
| 627 | + <FilterPanel |
| 628 | + sectionsData={oneFilterSection} |
| 629 | + resultsCount={`${filteredItems.length} items found`} |
| 630 | + filterButtonText="Filter items" |
| 631 | + applyButtonText="Apply filter (Client-side only)" |
| 632 | + ga4BaseEvent={{ event_name: "filter_items", type: "client_only" }} |
| 633 | + /> |
| 634 | + </form> |
| 635 | + |
| 636 | + <!-- Display current filter --> |
| 637 | + <p class="govuk-body"> |
| 638 | + <strong>Selected Category:</strong> |
| 639 | + {selectedCategory === "all" ? "All items" : selectedCategory} |
| 640 | + </p> |
| 641 | + |
| 642 | + <!-- Display results using Table component --> |
| 643 | + <div class="mt-8 border-t pt-4"> |
| 644 | + <h4 class="text-lg font-semibold mb-4"> |
| 645 | + Results ({filteredItems.length} items) |
| 646 | + </h4> |
| 647 | + <Table |
| 648 | + data={filteredItems} |
| 649 | + metaData={simpleMetaData} |
| 650 | + caption="Filtered Items" |
| 651 | + colourScale="Off" |
| 652 | + /> |
| 653 | + |
| 654 | + {#if filteredItems.length === 0} |
| 655 | + <p class="text-gray-500 italic mt-4">No items match your filter.</p> |
| 656 | + {/if} |
| 657 | + </div> |
| 658 | + </div> |
| 659 | + |
| 660 | + <CodeBlock code={clientSideOnlyCode} language="svelte"></CodeBlock> |
| 661 | +{/snippet} |
| 662 | + |
545 | 663 | {#snippet EnhancedFormExample()}
|
546 | 664 | <div class="p-5 bg-white">
|
547 | 665 | <h3 class="text-xl font-bold mb-4">
|
|
0 commit comments