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

Roles

Roles are semantic labels assigned to child components. They are defined in HTML and used by parent components to find, listen to, and coordinate their children.

<div data-component="Form">
    <button data-component="Button" data-roles="submit,primary">Submit</button>
    <button data-component="Button" data-roles="cancel">Cancel</button>
</div>

Here, the two ButtonComponent -s are given roles. These roles are not CSS classes and are not used for styling (although, theoretically, you can use [data-roles="cancel"] as a CSS selector, of course). Roles are a way to identify component instances inside the component hierarchy and assign "meaning" to individual component instances. In the example above, we have two buttons that are of the same component class ButtonComponent but clicking on them will probably produce different effects since ultimately it's the FormComponent(the parent) that decides what to do with events coming from children components that are assigned different roles.

Roles are a very simple concept, but they are central to composing components cleanly.

Defining and accessing roles

Roles are declared using data-roles. Multiple roles are comma-separated. When Qite initializes a component, it parses data-roles and stores them in this.roles. You normally do not manipulate this.roles directly. Instead, you use roles when searching for children or wiring events.

Finding children by role

A parent component can find its direct children by role:

this.findChildren({ roles: "submit" });

This returns only direct child components (not ancestors) that have the given role. The search is intentionally limited to direct children. If you need structure deeper than that, your hierarchy probably needs adjustment — roles are meant to express clear parent-child intent.

Roles in event wiring

Roles are most powerful when used together with events.

this.events.add([
    ["click", "submit", () => this.submit()],
    ["click", "cancel", () => this.cancel()],
    // ----------^--------------------------------
    //         roles
]);

In this example:

  • "click" refers to a DOM event.
  • "submit" and "cancel" refer to roles.

The parent listens only to click events coming from children with specific roles. The ButtonComponent itself does not know what "submit" means — it merely emits the "click" event and the parent interprets it. This keeps children generic and reusable, while parents define behavior.

Roles vs parts vs fields

We haven't looked at parts or fields yet, but it's still important to note here that roles may be confused with other concepts in Qite, so let's briefly go over it here:

  • Roles identify child components inside a parent.
  • Parts identify DOM elements inside a component (via data-part).
  • Fields represent structured component state (via data-field).
  • Flags represent boolean-like state that affects behavior or visibility.

Roles are about hierarchy and communication. Parts are about DOM structure and fields and flags are about state. That is to say, as you will see from the subsequent pages of this documentation, parts and fields can also be used as event sources when defining events — but in a slightly different way.

Choosing good names for roles

Use roles to describe intent, not appearance. Good role names express what the child represents in relation to its parent, such as "submit", "item", "toggle", "header", "cleanup"

A bad name, on the other hand, would be a name that repeats Component's own purpose. For instance, if the child component you're assigning the role to is an instance of a ButtonComponent and its role is "button"— it'd be a very useless name.

A parent doesn't need to know the exact component class of its child -- it should only care about the role the child plays. This allows you to replace a component implementation without rewriting parent logic.