Now.js Framework Documentation

Now.js Framework Documentation

data-on-load

EN 12 Apr 2026 04:55

data-on-load

Overview

data-on-load calls a global function after API-driven or binding-driven content is ready (similar concept to data-script, but different lifecycle). It runs on the element that declares the attribute and is intended ONLY for initialization that should happen after a payload has been inserted into the DOM. Typical callers are ApiComponent, FormManager, TableManager, and FormManager's declarative submit-result binding.

The function receives the TemplateManager context object as the second argument. In practice:

  • Use context.state for the full normalized payload.
  • Use context.data for the primary dataset when available.
  • For declarative form result binding, context.state contains the canonical schema and context.data usually contains the row array used by data-for="item in data".

Use it to:

  • Run per-section initialization after an API or form payload has been inserted into a container
  • Attach behavior that depends on the loaded data (e.g., populate maps, charts, third-party widgets)
  • Use the signature (element, context) where context.state is the full payload and context.data is the primary dataset when available

Basic Usage

<main>
  <section data-on-load="initFormLoad">
    <h2 data-text="data.title"></h2>
  </section>
</main>
function initFormLoad(element, context) {
  // element: DOM element with data-on-load
  // context.state: full payload
  // context.data: primary dataset when available
  console.log('Init section', element, context.state, context.data);

  // Optional cleanup
  return () => {
    console.log('Cleanup section');
  };
}

How it runs

  • ApiComponent: After rendering API data (or serving from cache), ApiComponent will run all [data-on-load] inside the component using the render context.
  • FormManager: When form data is loaded or when a successful AJAX submit re-binds a result target, FormManager will run [data-on-load] using the render context.
  • TableManager: When a table loads data from an API and renders its rows, TableManager will invoke [data-on-load] on the table element itself once after the render completes.

Note: TemplateManager/process lifecycle changed slightly in later framework versions — data-on-load is primarily intended for API-driven payloads, but FormManager will also invoke data-on-load after form initialization when there is no explicit data-load-api (for example when a form is inserted into a modal via the ResponseHandler). In that case FormManager passes a normalized payload (it prefers window._currentModalData when available, otherwise the current form values) so handlers can initialize behavior for modal or pre-rendered forms.

To avoid duplicate invocations, FormManager sets an internal flag when it has invoked data-on-load for a given form instance. If the form later receives an API payload (via data-load-api), the API-driven invocation will still run but duplicate calls are prevented by the FormManager flag.

Note: data-on-load is for API-driven loads only. For page-level initialization triggered by navigation, use data-script (RouterManager invokes data-script during navigation). The two hooks are separate and should not be interchanged.

Body-level usage (AppConfigManager)

When data-on-load is placed on the page <body> (for example to run logic after a combined config load), AppConfigManager executes that attribute and the function signature differs from the per-element handlers:

  • Normal per-element usage: handlers are called as window[fn](element, context) — signature (element, context) as described above.
  • Body-level usage (AppConfigManager): the attribute is compiled to a function and invoked as fn(site, theme, config) — where site is the site metadata object, theme is the current theme string, and config is the full config object containing site, theme and applied variables.

Example:

<body data-on-load="document.title = site.title; initHeader(site, theme, config)">
  <!-- available: site, theme, config -->
</body>

See the AppConfigManager documentation (docs/en/AppConfigManager.md) for more details and examples of using body-level data-on-load.

Function Signature

function initFn(element, context) {
  // element: HTMLElement with data-on-load
  // context.state: full TemplateManager payload
  // context.data: primary dataset when available
  // return optional cleanup function
}
Parameter Type Description
element HTMLElement Element bearing data-on-load
context Object TemplateManager context. Prefer context.state for the full payload and context.data for the primary dataset
Return Effect
undefined No cleanup
Function Called on cleanup (component/form teardown)

Tips

  • Prefer data-on-load for multiple independent areas; keep data-script for single entry-point logic.
  • If the goal is to derive display data from current form values, prefer FormManager watched API binding (data-watch-api) so the response can be rebound through normal directives without custom JavaScript.
  • Keep functions idempotent—reruns can happen after re-render.
  • Use returned cleanup to remove listeners/timers.

Example with declarative search results

<section id="results" data-on-load="initResults">
  <div data-for="item in data">
    <template>
      <article data-text="item.name"></article>
    </template>
  </div>
</section>
function initResults(element, context) {
  const rows = Array.isArray(context.data) ? context.data : [];
  const meta = context.state?.meta || {};
  console.log('Loaded rows:', rows.length, 'page:', meta.page);
}