App and Roots ​
Overview ​
Every Owl application has a root element, a set of templates, an environment and possibly a few other settings. The App class is a simple class that represents all of these elements. Here is an example:
const {Component, App } = owl;
class MyComponent extends Component { ... }
const app = new App(MyComponent, { props: {...}, templates: "..."});
app.mount(document.body);The basic workflow is: create an App instance configured with the root component, the templates, and possibly other settings. Then, we mount that instance somewhere in the DOM.
API ​
constructor(Root[, config]): first argument should be a component class (not an instance), and the optional second argument is a configuration object (see below).mount(target, options): first argument is an html element, and the optional second argument is an object with mounting options (see below). Mount the app to a target in the DOM. Note that this is an asynchronous operation: themountmethod returns a promise that resolves to the component instance whenever it is complete.The
optionobject is an object with the following keys:position (string): eitherfirst-childorlast-child. This option determines the position of the application in the target: either first or last child.
destroy(): destroys the application
Configuration ​
The config object is an object with some of the following keys:
env (object): if given, this will be the sharedenvgiven to each componentprops (object): the props given to the root componentdev (boolean, default=false): iftrue, the application is rendered indevmode;test (boolean, default=false):testmode is the same asdevmode, except that Owl will not log a message to warn that Owl is indevmode.translatableAttributes (string[]): a list of additional attributes that should be translated (see translations)translateFn (function): a function that will be called by owl to translate templates (see translations)templates (string | xml document | Record<string, string | TemplateFunction>): all the templates that will be used by the components created by the application. This may be a raw XML string, anXMLDocument, or a plain object mapping template names to either a template source string or a precompiled template function (as produced by thecompile_templatestool — see Precompiling templates).getTemplate ((s: string) => Element | Function | string | void): a function that will be called by owl when it needs a template. If undefined is returned, owl looks into the app templates.warnIfNoStaticProps (boolean, default=false): if true, Owl will log a warning whenever it encounters a component that does not provide a static props description.customDirectives (object): if given, the corresponding function on the object will be called on the template custom directives:t-custom-*(see Custom Directives).globalValues (object): Global object of elements available at compilations.
mount helper ​
Note that there is a mount helper to do that in just a line:
const { mount, Component } = owl;
class MyComponent extends Component {
...
}
mount(MyComponent, document.body, { props: {...}, templates: "..."});Here is the mount function signature:
mount(Component, target, config) with the following arguments:
Component: a component class (Root component of the app)target: an html element, where the component will be mounted as last childconfig (optional): a config object (the same as the App config object)
Most of the time, the mount helper is more convenient, but whenever one needs a reference to the actual Owl App, then using the App class directly is possible.
Roots ​
An application can have multiple roots. It is sometimes useful to instantiate sub components in places that are not managed by Owl, such as an html editor with dynamic content (the Knowledge application in Odoo).
To create a root, one can use the createRoot method, which takes two arguments:
Component: a component class (Root component of the app)config (optional): a config object that may contain apropsobject or aenvobject.
The createRoot method returns an object with prepare, mount, and destroy methods.
const root = app.createRoot(MyComponent, { props: { someProps: true } });
await root.mount(targetElement);
// later
root.destroy();Note that, like with owl App, it is the responsibility of the code that created the root to properly destroy it (before it has been removed from the DOM!). Owl has no way of doing it itself.
Two-phase mounting: prepare and mount ​
mount(target) is the common case and does everything in one step: start the render phase, wait for onWillStart callbacks to settle, then attach to the target. For more control, the root exposes these as two distinct phases:
prepare()starts the render phase without a DOM target. Descendants'onWillStartfires immediately, and the bdom is built in memory. Returns aPromise<void>that resolves once the render phase is complete. Idempotent — a second call returns the same promise. No DOM elements exist yet.mount(target, options?)attaches the prepared bdom intotargetand firesonMountedhooks. Callingmountwithout a priorprepareprepares implicitly. Returns a promise that resolves with the component instance.
The pattern is useful for:
- Pre-warming: start loading a subtree's data before you have a place to put it.
- Off-screen rendering: build the DOM in memory, inspect or pre-measure it, then mount later.
- Parallel loading: call
prepare()on multiple roots at once and wait onPromise.all([...])before mounting them.
const root = app.createRoot(MyComponent, { props });
// Kick off willStart now, in parallel with other work.
const ready = root.prepare();
// ... later, when the target is known ...
await ready;
await root.mount(targetElement);If you call prepare() but never mount(), the root never attaches to the DOM. destroy() still cleans up the prepared subtree in either case.
validateTarget runs at mount time, not at prepare, so a bad target surfaces synchronously when you actually try to mount.
Loading templates ​
Most applications will need to load templates whenever they start. Here is what it could look like in practice:
// in the main js file:
const { mount } = owl;
// async, so we can use async/await
(async function setup() {
const templates = await loadFile(`/some/endpoint/that/return/templates`);
const env = {
_t: someTranslateFn,
templates,
// possibly other stuff
};
mount(Root, document.body, { env });
})();Dev mode ​
Dev mode activates some additional checks and developer amenities:
- Props validation is performed
- t-foreach loops check for key unicity
- Lifecycle hooks are wrapped to report their errors in a more developer-friendly way
- onWillStart will emit a warning in the console when it takes longer than 3 seconds in an effort to ease debugging the presence of deadlocks