Clone on Gitea
Introduction
Explained by ducks
FAQ
Getting Started
Components
Component Basics
Auto Initialization From DOM
Templates
Children and Parents
Roles
Strictness
Fields
What is a Field
Binding Fields to DOM
Reading and Writing Fields
Value Casting
Flags
Events
Overview
Event Handlers
DOM Events
Custom Events
Propagation and Flow
Advanced Event Control
Beyond Components
States
Overview
StateEngine
DisplayStateEngine
Field Matchers
Ordering and priority
Debugging
Advanced usage
Ajax
ComponentUI
VirtualForm
Unit Testing
Helpers
Overview
Cookies
Arrays

Reading and Writing Fields

Fields are meant to be used directly from JavaScript. You read them with get(), update them with set(), and Qite keeps the DOM in sync.

Here's minimal example in HTML:

<div data-component="Counter" data-count="0">
    <span data-field="count"></span>
    <button data-component="Button" data-roles="inc">+</button>
</div>

And the corresponding Qite component code:

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

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

        this.events.add([
            ["click", "inc", () => this.fields.set("count", this.fields.get("count") + 1)],
        ]);
    }
}
Qite.components.Counter = CounterComponent;

So when count changes, Qite updates every DOM binding for that field

Reading fields

Read a field value with:

let count = this.fields.get("count");

You can also fetch current values of all fields as an object:

let all_fields = this.fields.all;

And if you want to check whether a field exists:

if (this.fields.has("count")) { ... }

Writing fields

Set a single field:

this.fields.set("count", 10);

Or set many fields at once by passing an object:

this.fields.set({
    count: 0,
    label: "Total",
});

Qite updates the component state first, then writes the new values into DOM using the bindings described on the "Binding Fields to DOM" page of this documentation.

set() returns the names of fields that actually changed. If nothing changed, it returns false. This is mostly useful in tests or when you want to conditionally do work based on what changed.

What happens on change

When you call this.fields.set(...), Qite performs two actions:

  • It writes the new value into the component fields object.
  • It writes the new value into DOM (through the field bindings).

Then it publishes a "field_change" event on the component, with the list of field names that changed. This is how states stay reactive without any render cycle.

Reading from DOM on purpose

Normally, you treat fields as your component state and you update them with this.fields.set(...)

But sometimes the browser changes DOM on its own, especially for form controls. For example, the user types into an <input>, and the browser updates the input value. In those cases you may want to pull the current value back into fields. For that reason, BaseComponent provides:

this.updateFieldsFromDOM();

This reads values from DOM using the same binding rules (the data-field and data-field-map attrbiutes) and updates this.fields to match. A common pattern is to call it inside a DOM input event handler:

this.events.add([
    ["@input", "self", () => this.updateFieldsFromDOM()],
]);

This keeps fields in sync with user input without you manually reading and writing DOM values.

Form fields and the corresponding browser "input" event here are given as examples to illustrate how to update fields from DOM. If you're building forms with Qite, you probably want to use FormFieldComponent and TextInputComponent standard comopnents provided by Qite — they offer useful functionality that you probably don't want to build on your own.

A simple rule

If a value is a field, update it through this.fields.set(...). If the browser is the one mutating DOM (inputs), pull it back in with this.updateFieldsFromDOM()

Methods you will commonly use

  • this.fields.get(name) reads a field.
  • this.fields.set(name, value) updates a single field.
  • this.fields.set({ ... }) updates many fields at once.
  • this.fields.all returns all fields as an object.
  • this.fields.has(name) checks if field exists.
  • this.updateFieldsFromDOM() syncs fields from DOM and publishes field_change