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.