NodeManager And Forms
NodeManager is the runtime object behind every node response.
Nodes describe the UI. NodeManager carries the request context while those nodes handle the request, prepare their response and serialize themselves for React.
What NodeManager Stores
When a node endpoint is called, NodeManager reads:
- the root node returned by the controller or resource;
- whether this is the first request for that node tree;
- persisted node state from the frontend;
- hidden node IDs;
- URL params and query values sent by the frontend.
After the node tree runs, NodeManager::toArray() returns the serialized root node, response state, hidden node IDs and subnode IDs.
Request Then Response
The lifecycle has two passes:
$manager = new NodeManager($rootNode);
$manager->handleNodeRequest();
$manager->handleNodeResponse();
return response()->json($manager->toArray());
toResponse() does this for you. Use request callbacks for incoming events and response callbacks for derived output:
$button->onNodeRequest(function (NodeManager $manager) {
if (! $manager->hasState($this->id)) {
return;
}
$manager->reloadGlobals();
});
$card->onNodeResponse(function (NodeManager $manager) {
if ($manager->isInitialRequest()) {
$this->addClassName('animate-fade-in');
}
});
State
State is keyed by node ID or by framework action keys. A state value can decide whether it should persist in the response, the next request, or both.
Common uses:
- a button click creates state for the button ID;
- a form keeps field values under the form ID;
- a table keeps pagination, filter and sorting state;
- framework actions request navigation, global reloads or external node reloads.
Use stable IDs for nodes that should be reloaded, hidden, shown or read by callbacks:
$manager->getNodeByIdOrFail('created-api-token');
$manager->hideNodeById('advanced-settings');
$manager->reloadExternalNodes(['settings/api-tokens-page']);
URL Context
The frontend sends the current route params and query values with node requests. Backend nodes can read those values without parsing URLs manually:
$manager->getUrlParam('resourceName');
$manager->getUrlQuery('tab', 'overview');
Use this for display state that truly belongs to the browser URL. Use form state or node state for interactive state that belongs to the node tree.
Forms
FormNode describes a backend-driven form. Form is the request-time object passed to field callbacks and form success/error callbacks.
The split matters:
FormNodeknows the endpoint, fields, model, resource, footer layout and form options.Formknows the current submitted field values and the currentNodeManager.
That lets field callbacks react to other fields without turning the controller into a large conditional block.
Reading And Setting Values
$field->onUpdate(function (Form $form, mixed $value) {
if (! $value) {
$form->setFieldValue('slug', null);
return;
}
$form->setFieldValue('slug', Str::slug($value));
});
setFieldValue() updates the form state and records a response mutation so the frontend can update the visible form.
Pass triggerOnUpdate: true when setting one field should immediately run that field's own update callback:
$form->setFieldValue('country', 'nl', triggerOnUpdate: true);
Dependencies
Fields can depend on other fields. When the source field updates, Qore runs the dependent callbacks after the source callback.
Use dependencies for things like:
- clearing a city field when the country changes;
- loading select options based on another select;
- updating preview nodes;
- enabling or disabling fields based on form state.
Success And Error State
After submit, Form can read the response state:
$formNode->onSuccess(function (Form $form) {
$success = $form->getSuccessState();
$data = $success?->getValue()['data'] ?? [];
if (! isset($data['plain_text_token'])) {
return;
}
$copyText = $form->getNodeManager()->getNodeByIdOrFail('created-api-token');
$copyText->setProperty('text', $data['plain_text_token']);
});
This is the pattern used by the API token page: the backend receives the token from the submit response, finds the copy-text node by ID and updates it for the next frontend render.
Resource Context
When a resource page returns nodes, the manager can carry the current QoreResource. Form can also expose the current model, resource, parent resource and parent model.
That context is why fields can be reused across create, edit, detail, relation tables and custom resource layouts without each controller manually passing the same data around.