Layout & Components

Overview of View Types in Stratox

Stratox supports three primary types of views, designed to help you structure and manage your application's UI efficiently:

  1. Layout: Serves is the starting point for you to show views. You then extend your layout views content with block and partial views.

  2. Partial: Extends the layout with content. Partials are self-contained, but as they are statically loadad and counts as a part of the layout, you will need to update the state to update it's content meaning all views will be refreshed.

  3. Block: Extends the layout with dynamic content. Blocks are self-contained, allowing for updates without refreshing the entire layout.

Note: Layout and Block views are initialized similarly but differ in load functionality.


Using Layout Views

Layout views is the starting point for you to show views. You then extend your layout views content with block and partial views.

Example: Basic Layout Initialization

import ProductPage from "@/templates/views/ProductPage";

const { view, item } = this.layout(ProductPage, {
    title: "My text 1",
    description: "Lorem ipsum dolor",
});

This code adds and displays the ProductPage view if it exists. The view object is the main instance, while item represents the view's context. Both can manage or update data in the layout but are optional for most cases.


Using Partial Views

Example: Adding a Partial View

import Increment from "@/templates/views/blocks/Increment";

export default function ProductPage({ props, view }) {
    return `
        <article class="relative card-1 border-bottom ingress">
            <div class="wrapper md">
                <h1 class="headline-1">${props.title}</h1>
                <p>${props.description}</p>
            </div>
        </article>
        <div class="increment">
            ${view.partial(Increment, { title: "Start incrementing", increment: 0 })}
        </div>
    `;
}

Partials update the entire layout when refreshed, making them useful for integrating smaller components within larger views.


Using Block Views

Example: Adding a Block View

import Increment from "@/templates/views/blocks/Increment";

export default function ProductPage({ props, view }) {
    return `
        <article class="relative card-1 border-bottom ingress">
            <div class="wrapper md">
                <h1 class="headline-1">${props.title}</h1>
                <p>${props.description}</p>
            </div>
        </article>
        <div class="increment">
            ${view.block(Increment, { title: "Start incrementing", increment: 0 })}
        </div>
    `;
}

Blocks are dynamic components that can be updated independently, making them ideal for complex, interactive elements like sortable tables or modals.


Protecting Against XSS (Cross-Site Scripting)

To safeguard against XSS vulnerabilities, encapsulate potentially injectable data within double curly braces:

Example: Escaping Data

export default function TextComponent({ props, view }) {
    return `
        <article class="relative card-1 border-bottom ingress">
            <div class="wrapper md">
                <h1 class="headline-1">${{props.title}}</h1>
                <p>${{props.description}}</p>
            </div>
        </article>
    `;
}

This approach is especially crucial for user-generated content, query strings, or third-party data.


Loading Views Multiple Times

To reuse the same view with different data, provide unique names for each instance:

Example: Reusing Layouts

const { view: view1, item: item1 } = this.layout({ ProductPage1: ProductPage }, {
    title: "My text 1",
    description: "lorem ipsum dolor",
});

const { view: view2, item: item2 } = this.layout({ ProductPage2: ProductPage }, {
    title: "My text 2",
    description: "lorem ipsum dolor",
});

By appending unique identifiers (e.g., ProductPage1, ProductPage2), you can load the same layout multiple times efficiently.


Quick Load View

For simple components, you can define and load views directly within your code:

Example: Inline Layout

this.layout(() => `
    <header class="ingress mb">
        <h2 class="headline-3 title">Hello World</h2>
        <p>Lorem ipsum dolor sit amet.</p>
    </header>`);

this.partial({
    bindToName: function({ props }) {
        return `
        <header class="ingress mb">
            <h2 class="headline-3 title">${props.title}</h2>
            <p>Lorem ipsum dolor sit amet.</p>
        </header>`;
    }
}, {
    headline: "My text 2",
});

this.block(({ props }) => `
    <header class="ingress mb">
        <h2 class="headline-3 title">${props.title}</h2>
        <p>Lorem ipsum dolor sit amet.</p>
    </header>`, {
    headline: "My text 2",
});

This approach is ideal for quick prototyping or when working with minimal HTML components.


Asynchronous Layout Loading

To optimize performance, load layouts asynchronously to reduce the initial bundle size:

Example: Dynamic Layout Loading

this.layout("Ingress", {
    title: "Welcome!",
    description: "lorem ipsum dolor",
});

Ensure the Ingress.js module exists in ./src/templates/views/. It will be dynamically loaded when accessed.

Example: Reusing Layouts with Identifiers

this.layout("text#ingressView1", {
    title: "My text 1",
    description: "Lorem ipsum dolor",
});

this.layout("text#ingressView2", {
    title: "My text 2",
    description: "Lorem ipsum dolor",
});

Appending unique identifiers (e.g., #ingressView1, #ingressView2) allows efficient reuse of layouts.


By following these guidelines, you can fully leverage Stratox's view system for creating dynamic, efficient, and secure web applications.

Last updated