| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- using Spry;
- /**
- * ComponentsTemplateSyntaxPage - Documentation for Spry template syntax
- *
- * This page covers all the special HTML attributes and elements used in
- * Spry component templates.
- */
- public class ComponentsTemplateSyntaxPage : PageComponent {
-
- public const string ROUTE = "/components/template-syntax";
-
- public override string markup { get {
- return """
- <div sid="page" class="doc-content">
- <h1>Template Syntax</h1>
-
- <section class="doc-section">
- <p>
- Spry extends HTML with special attributes that enable reactive behavior,
- component composition, and dynamic content. This page covers all the
- template syntax available in Spry components.
- </p>
- </section>
-
- <section class="doc-section">
- <h2>Special Attributes</h2>
-
- <h3><code>sid</code> - Spry ID</h3>
- <p>
- The <code>sid</code> attribute assigns a unique identifier to an element within
- a component. Use it to select and manipulate elements in your Vala code.
- </p>
-
- <spry-component name="CodeBlockComponent" sid="sid-html"/>
- <spry-component name="CodeBlockComponent" sid="sid-vala"/>
- </section>
-
- <section class="doc-section">
- <h3><code>spry-action</code> - HTMX Action Binding</h3>
- <p>
- The <code>spry-action</code> attribute binds an element to trigger a component action
- when interacted with. The action is sent to the server via HTMX.
- </p>
-
- <spry-component name="CodeBlockComponent" sid="action-example"/>
-
- <p>
- See the <a href="/components/actions">Actions</a> page for more details.
- </p>
- </section>
-
- <section class="doc-section">
- <h3><code>spry-target</code> - Scoped Targeting</h3>
- <p>
- The <code>spry-target</code> attribute specifies which element should be replaced
- when an action completes. It targets elements by their <code>sid</code> within the
- same component.
- </p>
-
- <spry-component name="CodeBlockComponent" sid="target-example"/>
- </section>
-
- <section class="doc-section">
- <h3><code>spry-global</code> - Out-of-Band Swaps</h3>
- <p>
- The <code>spry-global</code> attribute marks an element for out-of-band updates.
- When included in a response, HTMX will swap this element anywhere on the page
- that has a matching <code>id</code>.
- </p>
-
- <spry-component name="CodeBlockComponent" sid="global-html"/>
- <spry-component name="CodeBlockComponent" sid="global-vala"/>
- </section>
-
- <section class="doc-section">
- <h3><code>*-expr</code> - Expression Attributes</h3>
- <p>
- Expression attributes dynamically set HTML attributes based on component properties.
- Use <code>content-expr</code> for text content, <code>class-*-expr</code> for
- conditional classes, and <code>any-attr-expr</code> for any other attribute.
- </p>
-
- <spry-component name="CodeBlockComponent" sid="expr-example"/>
- </section>
-
- <section class="doc-section">
- <h3><code>spry-if</code> / <code>spry-else-if</code> / <code>spry-else</code> - Conditionals</h3>
- <p>
- Use these attributes for conditional rendering. Only elements with truthy
- conditions will be included in the output.
- </p>
-
- <spry-component name="CodeBlockComponent" sid="conditional-example"/>
- </section>
-
- <section class="doc-section">
- <h3><code>spry-per-*</code> - Loop Rendering</h3>
- <p>
- Use <code>spry-per-{varname}="expression"</code> to iterate over collections.
- The variable name becomes available in nested expressions.
- </p>
-
- <spry-component name="CodeBlockComponent" sid="loop-example"/>
- </section>
-
- <section class="doc-section">
- <h2>Special Elements</h2>
-
- <h3><code><spry-outlet></code> - Child Component Outlets</h3>
- <p>
- Outlets are placeholders where child components can be inserted dynamically.
- Use <code>set_outlet_children()</code> to populate outlets.
- </p>
-
- <spry-component name="CodeBlockComponent" sid="outlet-example"/>
-
- <p>
- See the <a href="/components/outlets">Outlets</a> page for more details.
- </p>
- </section>
-
- <section class="doc-section">
- <h3><code><spry-component></code> - Declarative Child Components</h3>
- <p>
- Use <code><spry-component></code> to declare child components directly in
- your template. Access them with <code>get_component_child<T>()</code>.
- </p>
-
- <spry-component name="CodeBlockComponent" sid="component-html"/>
- <spry-component name="CodeBlockComponent" sid="component-vala"/>
- </section>
-
- <section class="doc-section">
- <h3><code>spry-res</code> - Static Resources</h3>
- <p>
- Use <code>spry-res</code> to reference Spry's built-in static resources.
- This resolves to <code>/_spry/res/{resource-name}</code> automatically.
- </p>
-
- <spry-component name="CodeBlockComponent" sid="res-example"/>
- </section>
-
- <section class="doc-section">
- <h2>Next Steps</h2>
- <div class="nav-cards">
- <a href="/components/actions" class="nav-card">
- <h3>Actions →</h3>
- <p>Handle user interactions with actions</p>
- </a>
- <a href="/components/outlets" class="nav-card">
- <h3>Outlets →</h3>
- <p>Compose components with outlets</p>
- </a>
- <a href="/components/continuations" class="nav-card">
- <h3>Continuations →</h3>
- <p>Real-time updates with SSE</p>
- </a>
- </div>
- </section>
- </div>
- """;
- }}
-
- public override async void prepare() throws Error {
- // sid examples
- var sid_html = get_component_child<CodeBlockComponent>("sid-html");
- sid_html.language = "HTML";
- sid_html.code = """<div sid="container">
- <span sid="title">Hello</span>
- <button sid="submit-btn">Submit</button>
- </div>""";
-
- var sid_vala = get_component_child<CodeBlockComponent>("sid-vala");
- sid_vala.language = "Vala";
- sid_vala.code = """// Access elements by sid in prepare() or handle_action()
- this["title"].text_content = "Updated Title";
- this["submit-btn"].set_attribute("disabled", "true");""";
-
- // spry-action example
- var action_example = get_component_child<CodeBlockComponent>("action-example");
- action_example.language = "HTML";
- action_example.code = """<!-- Same-component action -->
- <button spry-action=":Toggle">Toggle</button>
- <!-- Cross-component action -->
- <button spry-action="ListComponent:Add">Add Item</button>""";
-
- // spry-target example
- var target_example = get_component_child<CodeBlockComponent>("target-example");
- target_example.language = "HTML";
- target_example.code = """<div sid="item" class="item">
- <span sid="title">Item Title</span>
- <button spry-action=":Delete" spry-target="item">Delete</button>
- </div>""";
-
- // spry-global examples
- var global_html = get_component_child<CodeBlockComponent>("global-html");
- global_html.language = "HTML";
- global_html.code = """<!-- In HeaderComponent -->
- <div id="header" spry-global="header">
- <h1>Todo App</h1>
- <span sid="count">0 items</span>
- </div>""";
-
- var global_vala = get_component_child<CodeBlockComponent>("global-vala");
- global_vala.language = "Vala";
- global_vala.code = """// In another component's handle_action()
- add_globals_from(header); // Includes header in response for OOB swap""";
-
- // Expression attributes example
- var expr_example = get_component_child<CodeBlockComponent>("expr-example");
- expr_example.language = "HTML";
- expr_example.code = """<!-- Content expression -->
- <span content-expr='format("%i%%", this.percent)'>0%</span>
- <!-- Style expression -->
- <div style-width-expr='format("%i%%", this.percent)'></div>
- <!-- Conditional class -->
- <div class-completed-expr="this.is_completed">Task</div>
- <!-- Any attribute expression -->
- <input disabled-expr="this.is_readonly">""";
-
- // Conditional example
- var conditional_example = get_component_child<CodeBlockComponent>("conditional-example");
- conditional_example.language = "HTML";
- conditional_example.code = """<div spry-if="this.is_admin">Admin Panel</div>
- <div spry-else-if="this.is_moderator">Moderator Panel</div>
- <div spry-else>User Panel</div>""";
-
- // Loop example
- var loop_example = get_component_child<CodeBlockComponent>("loop-example");
- loop_example.language = "HTML";
- loop_example.code = """<ul>
- <li spry-per-task="this.tasks">
- <span content-expr="task.name"></span>
- <span content-expr="task.status"></span>
- </li>
- </ul>""";
-
- // Outlet example
- var outlet_example = get_component_child<CodeBlockComponent>("outlet-example");
- outlet_example.language = "HTML";
- outlet_example.code = """<div sid="list">
- <spry-outlet sid="items"/>
- </div>""";
-
- // Component examples
- var component_html = get_component_child<CodeBlockComponent>("component-html");
- component_html.language = "HTML";
- component_html.code = """<div>
- <spry-component name="HeaderComponent" sid="header"/>
- <spry-component name="TodoListComponent" sid="todo-list"/>
- <spry-component name="FooterComponent" sid="footer"/>
- </div>""";
-
- var component_vala = get_component_child<CodeBlockComponent>("component-vala");
- component_vala.language = "Vala";
- component_vala.code = """public override async void prepare() throws Error {
- var header = get_component_child<HeaderComponent>("header");
- header.title = "My App";
- }""";
-
- // Static resources example
- var res_example = get_component_child<CodeBlockComponent>("res-example");
- res_example.language = "HTML";
- res_example.code = """<script spry-res="htmx.js"></script>
- <script spry-res="htmx-sse.js"></script>""";
- }
- }
|