Introduction
FAQ
Getting Started
Components
Component Basics
Auto Initialization From DOM
Initializing From Templates

Initializing from Templates

Qite does not use render functions — it instead uses native HTML <template> elements. Templates allow you to define component markup in HTML and instantiate it dynamically when needed.

The browser already provides <template> as a safe, inert container for markup. Its content is not rendered until cloned. Qite builds on that instead of inventing its own rendering abstraction.

When to use templates

Templates are very useful when you don't know ahead of time how many instances of a particular component you might need on your page as time passes and things change. For instance, you might want to dynamically add form fields (which you decided are going to be instances of TextInputComponent class) if user, say, needs to add more delivery addresses into his profile.

A good way to handle this would be to have an "Add address" button which, when clicked, creates a new TextInputComponent using a template.

Defining the address template

You would first define a template in your HTML:

<template 
  data-component="TextInput"
  data-tag-name="div"
  data-qtemplate-name="default"
>
    <label data-field="label"></label>
    <input data-part="value" name="" value=""/>
    <div class="hint" data-part="hint"></div>
    <div class="errors" data-field="validation_errors"></div>
</template>

This template describes how a TextInputComponent should be constructed. Nothing inside it is rendered immediately because <template> content is inert by default.

Instead of wrapping the component in a <div data-component="TextInput">, Qite reads data-component, data-tag-name and data-qtemplate-name directly from the <template> tag and constructs the root element for you.

  • data-component="TextInput" tells Qite which component class to instantiate.
  • data-tag-name="div" defines which HTML tag should be created.
  • data-qtemplate-name="default" gives this template a name.

When this template is used, Qite creates a <div data-component="TextInput"> element, inserts the template content inside it, scans it and instantiates a TextInputComponent

All standard Qite components have an .html file in their directory which contains the expected HTML structure. For TextInputComponent, check src/components/text_input/text_input.html. You can copy that structure and move it inside <template> tags.

Default vs named templates

A component may have more than one template.

The data-qtemplate-name attribute allows you to define multiple variations:

<template 
  data-component="TextInput"
  data-tag-name="div"
  data-qtemplate-name="default"
>
    <!-- default layout -->
</template>

<template 
  data-component="TextInput"
  data-tag-name="div"
  data-qtemplate-name="compact"
>
    <!-- compact layout -->
</template>

The template with name "default" is used automatically when no specific template is requested.

To explicitly choose a template:

TextInputComponent.create({
    parent: this,
    template_name: "compact"
});

If you omit template_name, Qite uses "default"

Adding address fields dynamically

Now suppose you have a parent component responsible for managing a list of delivery addresses.

import BaseComponent from "/assets/vendor/qite/src/components/base_component.js";
import TextInputComponent from "/assets/vendor/qite/src/components/text_input/text_input_component.js";

export default class DeliveryComponent extends BaseComponent {
    constructor(tree_node) {
        super(tree_node);

        this.events.add([
            ["click", "add_address", () => this.addAddress() ],
        ]);
    }

    addAddress() {
        TextInputComponent.create({
            parent: this,
            template_name: "default"
        });
    }
}

Qite.components.Delivery = DeliveryComponent;

And in HTML:

<div data-component="Delivery">
    <button data-component="Button" data-roles="add_address">
      Add address
    </button>
</div>

When the user clicks the button, addAddress() is called. TextInputComponent.create(...) then:

  1. Finds the <template> matching data-component="TextInput" and data-qtemplate-name="default"
  2. Creates a new root element with data-tag-name
  3. Inserts template content inside it.
  4. Appends it to the parent.
  5. Scans that subtree.
  6. Instantiates a new TextInputComponent
  7. Links it into the component hierarchy.

The newly created component behaves exactly like one that was present at page load.

Hierarchy and wiring

When you pass parent: this to create()

  • The new component is appended to this.children
  • Its parent property is set.
  • Event subscriptions are wired.
  • Its mounted promise is resolved after hierarchy attachment.

There is no special case for template-created components. They become first-class components in the tree.

Templates keep HTML in HTML

With this approach:

  • HTML structure lives in HTML.
  • Component behavior lives in JavaScript.
  • Styling lives in CSS.

You are not building HTML strings, not mixing markup inside JavaScript, and not re-rendering entire blocks. Qite clones structured DOM and attaches behavior to it.

Creating a component from a template triggers scanning only for the cloned subtree. It does not rescan the entire document.

What to read next

Now that you understand how to create components dynamically, the next page explains how parent and child components relate to each other in more detail.