### Quick Start Counter Example
Source: https://github.com/odoo/owl/blob/master/tools/site/index.html
A basic example demonstrating component creation, signal-based state management, and event handling in OWL. Mounts a counter component to the document body.
```javascript
import { Component, signal, mount, xml } from "@odoo/owl";
class Counter extends Component {
static template = xml`
`
count = signal(0);
increment() {
this.count.set(this.count() + 1);
}
decrement() {
this.count.set(this.count() - 1);
}
}
mount(Counter, document.body);
```
--------------------------------
### Provide TodoListPlugin from a Component
Source: https://github.com/odoo/owl/blob/master/tools/playground/samples/v3/tutorials/todo_list/8/readme.md
This code demonstrates how to make a plugin available to a component and its descendants using `providePlugins`. The `setup` method is used to both provide the plugin and get an instance of it for the current component.
```javascript
import { providePlugins, plugin } from "@odoo/owl";
class TodoList extends Component {
setup() {
providePlugins([TodoListPlugin]);
this.todoList = plugin(TodoListPlugin);
}
}
```
--------------------------------
### Setup Lifecycle Method
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/component.md
The `setup` method is called after component construction and is the proper place to call hook functions.
```javascript
setup() {
useSetupAutofocus();
}
```
--------------------------------
### Validate Apps and Provide Plugins in Setup
Source: https://github.com/odoo/owl/blob/master/tools/playground/samples/v3/tutorials/hibou_os/12/readme.md
This snippet shows the `setup` method in an Owl component, where app descriptors are validated against a schema and plugins are collected and provided.
```javascript
import { assertType } from "@odoo/owl";
setup() {
for (const app of this.props.apps) {
assertType(app, APP_SCHEMA);
}
const appPlugins = this.props.apps.flatMap((app) => app.plugins || []);
providePlugins([WindowManagerPlugin, ...appPlugins]);
...
}
```
--------------------------------
### Owl Hook Rule Examples
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/hooks.md
Demonstrates the correct placement for calling hooks within a component's class fields or setup method. Incorrect usage in callbacks like onWillStart is also shown.
```js
// ok: hook called in a class field
class SomeComponent extends Component {
mouse = useMouse();
}
// also ok: hook called in setup
class SomeComponent extends Component {
setup() {
this.mouse = useMouse();
}
}
// not ok: the onWillStart callback runs after the component is set up
class SomeComponent extends Component {
setup() {
onWillStart(async () => {
this.mouse = useMouse();
});
}
}
```
--------------------------------
### Install Owl with npm
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/installation.md
Use npm to install the Owl package in your project. This is the standard method for projects with a build step.
```bash
npm install @odoo/owl
```
--------------------------------
### Install Owl Dependencies
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/tools/devtools.md
Installs the necessary dependencies for the Owl project.
```bash
npm install
```
--------------------------------
### Registering onWillStart Hook
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/component.md
Use the `onWillStart` hook within `setup` to perform actions before the initial rendering, such as loading data. Callbacks are run in parallel.
```javascript
setup() {
onWillStart(async () => {
this.data = await this.loadData()
});
}
```
--------------------------------
### Providing StoragePlugin Globally
Source: https://github.com/odoo/owl/blob/master/tools/playground/samples/v3/tutorials/todo_list/10/readme.md
Example of how to provide the StoragePlugin as a global service to the entire Owl application during the mount process.
```javascript
import { StoragePlugin } from "./storage_plugin";
mount(Root, document.body, { templates: TEMPLATES, dev: true, plugins: [StoragePlugin] });
```
--------------------------------
### useApp Hook Usage
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/hooks.md
Demonstrates how to retrieve the current App instance within a component's setup method using the useApp hook.
```javascript
setup() {
const app = useApp();
}
```
--------------------------------
### Notepad App Descriptor
Source: https://github.com/odoo/owl/blob/master/tools/playground/samples/v3/tutorials/hibou_os/7/readme.md
Example of a notepad app descriptor.
```javascript
// apps/notepad/index.js
import { NotepadApp } from "./notepad_app";
export const notepad = {
name: "Notepad",
icon: "📝",
window: NotepadApp,
};
```
--------------------------------
### Editor Component Example
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
This example defines an `Editor` component with a toolbar and an editable content area. It uses `providePlugins` to make various plugins available to the component and its children.
```javascript
class Editor extends Component {
static template = xml`
Toolbar
Editable zone
this can be edited. Try to select the word "ged"
`;
editable = signal.ref();
setup() {
providePlugins([ContentPlugin, SelectionPlugin, TextToolsPlugin, GEDPlugin], {
ContentPlugin: { el: this.editable },
});
this.textTools = plugin(TextToolsPlugin);
}
}
```
--------------------------------
### Capture and Run Component Scope
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/scope.md
Capture the current component's setup scope using `useScope()` and defer its execution using `scope.run()`. This allows code to be executed later as if it were still within the original setup context, enabling hook calls and plugin usage.
```javascript
class Form extends Component {
static template = xml``;
setup() {
const scope = useScope();
window.debugAttach = () => {
scope.run(() => {
// code executed here can call hooks, plugin(), etc.,
// just like during the original setup
});
};
}
}
```
--------------------------------
### Two-Phase Mounting with Prepare and Mount
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/app.md
Illustrates the two-phase mounting process. Use `prepare()` to start data loading and rendering in parallel, then `mount()` to attach the component to the DOM when the target is available. This pattern is useful for pre-warming data or off-screen rendering.
```javascript
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);
```
--------------------------------
### Clock App Descriptor
Source: https://github.com/odoo/owl/blob/master/tools/playground/samples/v3/tutorials/hibou_os/7/readme.md
Example of a clock app descriptor, importing necessary components.
```javascript
// apps/clock/index.js
import { ClockApp } from "./clock_app";
import { Clock as ClockSystray } from "./clock_systray";
export const clock = {
name: "Clock",
icon: "🕐",
window: ClockApp,
systrayItems: [ClockSystray],
};
```
--------------------------------
### Basic Plugin Example
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Demonstrates a simple Clock plugin and its usage within another plugin (A) and a Root component. Shows how to define a plugin, manage its lifecycle, and inject it into other plugins and components.
```javascript
class Clock extends Plugin {
value = signal(1);
setup() {
const interval = setInterval(() => {
this.value.set(this.value() + 1);
}, 1000);
onWillDestroy(() => {
clearInterval(interval);
});
}
}
class A extends Plugin {
// import the instance of plugin Clock in A
clock = plugin(Clock);
mcm = computed(() => 2 * this.clock.value());
}
class Root extends Component {
static template = xml``;
a = plugin(A); // import plugin A into component
}
mount(Root, document.body, { plugins: [Clock, A] });
```
--------------------------------
### Migrate `mounted` lifecycle method to `setup` hook
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/migration_owl1_to_owl2.md
Component lifecycle methods like `mounted` are removed in Owl 2 and should be defined within the `setup` function using hooks.
```javascript
class MyComponent extends Component {
mounted() {
// do something
}
}
```
```javascript
class MyComponent extends Component {
setup() {
onMounted(() => {
// do something
});
}
}
```
--------------------------------
### Expression Evaluation Example
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/template_syntax.md
Demonstrates how JavaScript expressions in QWeb are converted to context lookups.
```javascript
context["a"] + context["b"].c(context["d"]);
```
--------------------------------
### Provide Component-Level Plugin Configuration
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/plugins.md
Configuration for plugins can be provided when using `providePlugins` in a component's `setup` method by passing a configuration object as the second argument.
```javascript
setup() {
providePlugins([ApiPlugin], { apiBaseUrl: "/api" });
}
```
--------------------------------
### Mount a Component using the mount Helper
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/app.md
Use the `mount` helper for the common case of attaching a root component to the DOM. It handles App creation and root setup in a single call.
```javascript
import { Component, mount, xml } from "@odoo/owl";
class MyComponent extends Component {
static template = xml`
Hello
`;
}
await mount(MyComponent, document.body);
```
--------------------------------
### Get an entry from a registry
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/registries.md
Use the `get` method to retrieve an entry by its key. If the key is missing and no default value is provided, it throws an `OwlError`. A default value can be supplied to be returned instead.
```javascript
views.get("list"); // ListComponent
views.get("kanban"); // throws OwlError
views.get("kanban", null); // returns null
```
--------------------------------
### App Descriptor Example
Source: https://github.com/odoo/owl/blob/master/tools/playground/samples/v3/tutorials/hibou_os/7/readme.md
Defines the structure for an app descriptor object, including its name, icon, window component, and optional systray items.
```javascript
export const clock = {
name: "Clock",
icon: "🕐",
window: ClockApp,
systrayItems: [ClockSystray],
};
```
--------------------------------
### Rendering Static HTML
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/template_syntax.md
Example of a static HTML node that is rendered as itself.
```xml
hello
```
--------------------------------
### Quick Example: Todo List Component
Source: https://github.com/odoo/owl/blob/master/README.md
Demonstrates Owl's reactivity with signals and computed values. The UI automatically updates as the 'todos' signal changes. This component manages a list of todos, allows adding new ones via Enter key, and displays the remaining items.
```javascript
import { Component, signal, computed, mount, xml } from "@odoo/owl";
class TodoList extends Component {
static template = xml`
item(s) remaining
`;
todos = signal.Array([
{ id: 1, text: "Learn Owl", done: false },
{ id: 2, text: "Build something", done: false },
]);
remaining = computed(() => this.todos().filter((t) => !t.done).length);
onKeydown(ev) {
if (ev.key === "Enter" && ev.target.value) {
this.todos.push({
id: Date.now(),
text: ev.target.value,
done: false,
});
ev.target.value = "";
}
}
}
mount(TodoList, document.body);
```
--------------------------------
### Run Owl Devtools in Development Mode for Firefox
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/tools/devtools.md
Starts the Owl Devtools extension in development mode for Firefox, avoiding recompilation.
```bash
npm run dev:devtools-firefox
```
--------------------------------
### Plugin System with Scoped Providers
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Illustrates advanced plugin usage with `providePlugins` to make plugins available only to specific components and their children. This example shows how to manage plugin scope and dependency injection in a hierarchical component structure.
```javascript
import {
Component,
signal,
mount,
Plugin,
plugin,
providePlugins,
computed,
xml,
onWillDestroy,
} from "@odoo/owl";
class Clock extends Plugin {
value = signal(1);
setup() {
const interval = setInterval(() => {
this.value.set(this.value() + 1);
}, 1000);
onWillDestroy(() => {
clearInterval(interval);
});
}
}
class A extends Plugin {
// import the instance of plugin Clock in A
clock = plugin(Clock);
mcm = computed(() => 2 * this.clock.value());
}
class ChildChild extends Component {
static template = xml``;
a = plugin(A);
}
class Child extends Component {
static components = { ChildChild };
static template = xml``;
// cannot import A here => no provider
// a = plugin(A);
setup() {
providePlugins([A]);
// can now import A
}
}
class Root extends Component {
static components = { Child };
static template = xml``;
// cannot import A => no provider
// a = plugin(A);
}
// Clock is a global plugin (service)
mount(Root, document.body, { plugins: [Clock] });
```
--------------------------------
### Dynamic List of Counters with Signals and Computed Properties
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Illustrates how to manage a dynamic list of counters using signals and proxy, and how to display a computed sum of these counters. This example requires importing Component, signal, mount, computed, xml, t, proxy, and props.
```javascript
import { Component, signal, mount, computed, xml, t, proxy, props } from "@odoo/owl";
class Counter extends Component {
static template = xml`
`;
counters = proxy([signal(1), signal(2)]);
sum = computed(() => this.counters.reduce((acc, value) => acc + value(), 0));
addCounter() {
this.counters.push(signal(0));
}
}
mount(Root, document.body);
```
--------------------------------
### Using Hooks within Plugins
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/plugins.md
Hooks like `useListener` and `useEffect` can be used within plugin `setup()` methods. They are automatically cleaned up when the plugin is destroyed.
```javascript
class KeyboardPlugin extends Plugin {
lastKey = signal("");
setup() {
useListener(window, "keydown", (ev) => {
this.lastKey.set(ev.key);
});
}
}
```
--------------------------------
### Manual Binding of Callback Props
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/props.md
Demonstrates the traditional method of binding a callback prop to the owner component using JavaScript's bind method within the setup function.
```js
class SomeComponent extends Component {
static template = xml`
`
setup() {
this.doSomething = this.doSomething.bind(this);
}
doSomething() {
// ...
}
}
```
--------------------------------
### Typing Signals with Initial Values
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/signals.md
Illustrates how signal types are inferred from initial values. Provides examples for arrays and nullable types using type validators.
```javascript
const ids = signal([], { type: t.array(t.number()) }); // Signal, not Signal
const selected = signal(null, { type: t.or([t.instanceOf(User), t.literal(null)]) }); // Signal
```
--------------------------------
### Using useApp Hook
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Demonstrates how to use the `useApp` hook to get the current active Owl App and create/manage roots. This is useful when dealing with multiple roots or needing direct access to the App instance.
```javascript
class Example extends Component {
static template = "...";
setup() {
const app = useApp();
const root = app.createRoot(SomeOtherComponent);
root.mount(targetEl);
onWillDestroy(() => {
root.destroy();
});
}
}
```
--------------------------------
### Owl 2.x Context Example
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Demonstrates how 't-out' in Owl 2.x could access 'val' from the template or fall back to the component's properties.
```xml
```
--------------------------------
### Portal Target Prop Examples
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/portal.md
Illustrates different ways to specify the target for the Portal component. The recommended method for in-tree targets is a t-ref signal. Direct HTMLElement and CSS selector strings are also supported.
```xml
.........
```
--------------------------------
### GEDPlugin Example
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
This snippet shows a custom plugin that adds a notification when specific text is selected. It utilizes `plugin` and `useEffect` for state management and side effects.
```javascript
class GEDPlugin extends Plugin {
selection = plugin(SelectionPlugin).selection;
notification = plugin(NotificationPlugin);
setup() {
useEffect(() => {
const s = this.selection();
if (s.text === "ged") {
this.notification.add("GED", "GED");
}
});
}
}
```
--------------------------------
### Provide Component-Level Plugins
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/plugins.md
Use `providePlugins` within a component's `setup` method to make plugins available only to that component and its descendants. These plugins are automatically destroyed when the component is destroyed.
```javascript
class FormView extends Component {
static template = xml``;
setup() {
providePlugins([FormModel, FormValidator]);
}
}
```
--------------------------------
### Register App Contributions
Source: https://github.com/odoo/owl/blob/master/tools/playground/samples/v3/tutorials/hibou_os/13/readme.md
Each app registers its provided components into the appropriate registries. This example shows how the clock app registers a menu item and a systray component.
```javascript
// apps/clock/index.js
import { menuItemRegistry, systrayItemRegistry } from "../../core/registries";
import { ClockApp } from "./clock_app";
import { Clock as ClockSystray } from "./clock_systray";
menuItemRegistry.add("clock", { name: "Clock", icon: "🕐", window: ClockApp });
systrayItemRegistry.add("clock", ClockSystray);
```
--------------------------------
### Owl 3.x Portal Plugin Implementation
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Owl 3.x replaces t-portal with a plugin system. This example shows how to implement a PortalPlugin and use the usePortal hook to manage portalled content.
```js
class PortalPlugin extends Plugin {
add(selector, component, props) {
// mount here a new root at selector location
}
}
function usePortal(selector, component, props) {
const portal = plugin(PortalPlugin);
const remove = portal.add(selector, component, props);
onWillDestroy(remove);
}
class PortalContent extends Component {
static template = xml`
`;
setup() {
usePortal(".someselector", PortalContent);
}
}
```
--------------------------------
### Forbidden 'block-' Tag in Owl Template
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/template_syntax.md
This example demonstrates a tag starting with 'block-' which is not accepted by Owl due to naming restrictions.
```xml
this will not be accepted by Owl
```
--------------------------------
### Register Cleanup with onWillDestroy
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/scope.md
Register cleanup code using `onWillDestroy` within the `setup` function. This callback will execute before the component scope is destroyed, allowing for resource deallocation like closing WebSockets.
```javascript
setup() {
const socket = new WebSocket(url);
onWillDestroy(() => socket.close());
}
```
--------------------------------
### Import Map Example for Odoo Owl
Source: https://github.com/odoo/owl/blob/master/tools/playground/static/playground.md
This snippet illustrates how the import map is constructed for Odoo Owl projects, mapping the core library and local files to their respective sources.
```javascript
{
imports: {
"@odoo/owl": "../owl.js",
"./otherFile.js": "blob:...",
...
}
}
```
--------------------------------
### Identifying Props in Component Templates
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/props.md
This example shows how attributes on a component tag are interpreted as props. Any attribute not starting with `t-` is considered a prop and its value is a JavaScript expression evaluated in the parent's context.
```xml
```
--------------------------------
### Migrating `this.env` and `useSubEnv` to Plugins
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/migration_owl2_to_owl3.md
Owl 3 removes `this.env` and `useSubEnv`, replacing them with a plugin system. This example demonstrates how to migrate from using `useSubEnv` to `providePlugins` and accessing plugin data via `plugin(PluginName)`.
```javascript
// owl 2
// in some component A setup:
setup() {
const someState = ...;
useSubEnv({dashboardState: someState})
}
// in some child component:
setup() {
const someState = this.env.dashboardState;
}
```
```javascript
// in owl 3, we will probably write a plugin
class DashboardPlugin extends Plugin {
state = ...
// and maybe some other helpers, computed functions, whatever
}
// in component A
setup() {
providePlugins([DashboardPlugin])
}
// in child component
setup() {
const dashboard = plugin(DashboardPlugin);
// here, we can read dashboard.state, or whatever
}
```
--------------------------------
### Load Templates at Startup
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/app.md
Loads templates from a server endpoint at application startup using `fetch` and mounts the root component. Ensure the endpoint returns raw XML template data.
```javascript
import { mount } from "@odoo/owl";
(async function setup() {
const templates = await fetch("/some/endpoint/that/returns/templates").then((r) => r.text());
await mount(Root, document.body, { templates });
})();
```
--------------------------------
### Get Current Time in JavaScript
Source: https://github.com/odoo/owl/blob/master/tools/playground/samples/v3/tutorials/hibou_os/2/readme.md
Use the Date object to get the current time and format it using `toLocaleTimeString()` for display.
```javascript
const now = new Date();
const time = now.toLocaleTimeString();
```
--------------------------------
### Basic Resource Usage
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Demonstrates the creation and basic usage of the `Resource` class, showing how to add items, check for their existence, and retrieve all items.
```javascript
const resource = new Resource({ name: "error handlers" });
resource.items(); // []
resource.add("value");
resource.items(); // ["value"]
resource.has("value"); // true
resource.has("string"); // false
```
--------------------------------
### Migrating Props from Owl 2.x to 3.x
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
This example shows the migration process from Owl 2.x static props and defaultProps to Owl 3.x explicit `props` function calls. Note the removal of the `slots` prop declaration.
```javascript
// owl 2.x
class SomeComponent extends Component {
static template = "...";
static props = {
name: String,
visible: { type: Boolean, optional: true },
immediate: { type: Boolean, optional: true },
leaveDuration: { type: Number, optional: true },
onLeave: { type: Function, optional: true },
slots: Object,
};
static defaultProps = {
leaveDuration: 100,
};
}
// owl 3.x
class SomeComponent extends Component {
static template = "...";
props = props({
name: t.string(),
visible: t.boolean().optional(),
immediate: t.boolean().optional(),
leaveDuration: t.number().optional(100),
onLeave: t.function().optional(),
// no need to grab the slot prop here
});
}
```
--------------------------------
### Mounting Apps in Main.js
Source: https://github.com/odoo/owl/blob/master/tools/playground/samples/v3/tutorials/hibou_os/7/readme.md
Demonstrates how to import app descriptors and pass them as props to the root Hibou component during mounting.
```javascript
import { clock } from "./apps/clock";
import { notepad } from "./apps/notepad";
import { calculator } from "./apps/calculator";
mount(Hibou, document.body, {
templates: TEMPLATES,
dev: true,
props: { apps: [clock, notepad, calculator] },
});
```
--------------------------------
### Owl 3.x Assert Type Example
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Example of using the `assertType` function to enforce a specific object structure with types in Owl 3.x.
```javascript
assertType(myObj, t.object({ id: t.number(), text: t.string()}));
```
--------------------------------
### Define Plugin Dependencies
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/plugins.md
A plugin can declare dependencies on other plugins using the `plugin()` function. If a dependency is not yet started, it will be auto-started when the dependent plugin is started.
```javascript
class RouterPlugin extends Plugin {
currentRoute = signal("/");
navigateTo(url) {
this.currentRoute.set(url);
}
}
class ActionPlugin extends Plugin {
router = plugin(RouterPlugin);
doAction(action) {
// ... perform action ...
this.router.navigateTo("/result");
}
}
```
--------------------------------
### Instantiate and mount component using `App` class
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/migration_owl1_to_owl2.md
Manual instantiation and mounting of components is deprecated. Use the `App` class for complex use cases or the `mount` helper for simpler ones.
```javascript
const root = new Root();
await root.mount(document.body);
```
```javascript
const app = new App(Root);
app.configure({ templates: ..., ...});
await app.mount(document.body);
```
--------------------------------
### Basic Registry Usage
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Demonstrates how to create, add items to, and retrieve items from a Registry. It also shows how to handle missing keys with a default value.
```javascript
const registry = new Registry({ name: "my registry" });
const obj = { a: 1 };
registry.add("key", obj);
registry.get("key") === obj; // true
registry.get("otherkey"); // throw error
registry.get("otherkey", 1) === 1; // true
```
--------------------------------
### Create and Mount a Root Component Manually
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/app.md
For advanced scenarios like multiple roots or deferred mounting, create an `App` instance directly and use `createRoot` to attach components. This provides finer control over the application lifecycle.
```javascript
import { App } from "@odoo/owl";
const app = new App({ templates });
const root = app.createRoot(MyComponent, { props: { user } });
await root.mount(document.body);
```
--------------------------------
### Async Plugin Initialization with onWillStart
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/plugins.md
Plugins can perform asynchronous initialization using `onWillStart()`. The owning `mount()` call or `providePlugins()` owner component will wait for all plugin `onWillStart` callbacks to complete before rendering.
```js
class SessionPlugin extends Plugin {
user = null;
setup() {
onWillStart(async ({ abortSignal }) => {
const res = await fetch("/api/session", { signal: abortSignal });
this.user = await res.json();
});
}
}
```
--------------------------------
### Create a Resource with Options
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/resources.md
Instantiate a Resource with a name for error messages and a validation schema for added items. The validation ensures items conform to the specified structure.
```javascript
const commands = new Resource({
name: "commands", // for error messages
validation: t.object({ label: t.string(), run: t.function() }),
});
```
--------------------------------
### Get Sorted Items
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/registries.md
Returns a reactive computed property that provides all values in the registry, sorted by their sequence.
```APIDOC
## items()
### Description
Returns a reactive computed property containing all values sorted by sequence.
### Method
`items`
### Parameters
None
### Request Example
```javascript
const sortedItems = registry.items();
```
### Response
#### Success Response (200)
Returns a reactive computed property.
#### Response Example
```javascript
// Reactive computed property returning an array of values
```
```
--------------------------------
### Use NotepadPlugin in NotepadApp
Source: https://github.com/odoo/owl/blob/master/tools/playground/samples/v3/tutorials/hibou_os/12/readme.md
Demonstrates how to integrate a plugin into an Owl component using the `plugin` helper and bind a signal to a UI element.
```javascript
import { plugin } from "@odoo/owl";
import { NotepadPlugin } from "./notepad_plugin";
notepad = plugin(NotepadPlugin);
```
--------------------------------
### Get Item
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/registries.md
Looks up an item in the registry by its key. Throws an `OwlError` if the key is missing and no default value is provided.
```APIDOC
## get(key, defaultValue?)
### Description
Looks up an item in the registry by its key.
### Method
`get`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
#### Parameters
- **key** (string) - Required - The key of the item to retrieve.
- **defaultValue** (any) - Optional - The default value to return if the key is not found.
### Request Example
```javascript
const value = registry.get("myKey", "default");
```
### Response
#### Success Response (200)
Returns the value associated with the key, or the default value if provided and the key is not found.
#### Response Example
```javascript
// The retrieved value
```
```
--------------------------------
### Owl 2.x Props Definition
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Example of defining component props using the object-based DSL in Owl 2.x.
```javascript
static props = {
mode: {
type: String,
optional: true,
},
readonly: { type: Boolean, optional: true },
onChange: { type: Function, optional: true },
onBlur: { type: Function, optional: true },
};
```
--------------------------------
### Conditional Rendering with t-if on t tag
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/template_syntax.md
Basic example of conditionally rendering content using the t-if directive on a tag.
```xml
ok
```
--------------------------------
### Awaiting Initial Data with onWillStart
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/computed_values.md
Shows how to use asyncComputed with onWillStart to ensure the component mounts only after the initial data is fetched and available. This prevents rendering with empty data.
```javascript
class UserCard extends Component {
static template = xml`
`;
user = asyncComputed(async ({ abortSignal }) => {
const res = await fetch(`/api/users/${userId()}`, { signal: abortSignal });
return res.json();
});
setup() {
onWillStart(() => this.user.currentPromise());
}
}
```
--------------------------------
### Create a Basic Registry
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/registries.md
Instantiate a new Registry. This is the simplest way to create a registry without any specific configuration.
```javascript
const views = new Registry();
```
--------------------------------
### Get Sorted Entries
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/registries.md
Returns a reactive computed property that provides all entries (key-value tuples) in the registry, sorted by their sequence.
```APIDOC
## entries()
### Description
Returns a reactive computed property containing all entries (key-value tuples) sorted by sequence.
### Method
`entries`
### Parameters
None
### Request Example
```javascript
const sortedEntries = registry.entries();
```
### Response
#### Success Response (200)
Returns a reactive computed property.
#### Response Example
```javascript
// Reactive computed property returning an array of [key, value] tuples
```
```
--------------------------------
### Create a Basic Resource
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/resources.md
Instantiate a new Resource object. This creates an empty, ordered collection.
```javascript
const commands = new Resource();
```
--------------------------------
### Example Usage of Custom Directive
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/template_syntax.md
Demonstrates how to use a custom directive in an XML template. The `t-custom-test_directive` will be processed by the configured function.
```xml
```
--------------------------------
### Provide App-Level Plugin Configuration
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/plugins.md
Configuration for plugins can be provided when mounting the application by passing a `config` object in the options.
```javascript
await mount(RootComponent, document.body, {
plugins: [ApiPlugin],
config: { apiBaseUrl: "https://api.example.com" },
});
```
--------------------------------
### get(key, defaultValue?)
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/registries.md
Retrieves the value associated with a given key. If the key is not found and no default value is provided, an error is thrown.
```APIDOC
## get(key, defaultValue?)
### Description
Returns the value for `key`. Throws an [`OwlError`](error_handling.md#owlerror) if the key is missing and no default value is provided.
### Method
`get(key: string, defaultValue?: any): any`
### Parameters
#### Path Parameters
- **key** (string) - Required - The key of the entry to retrieve.
- **defaultValue** (any) - Optional - The default value to return if the key is not found.
### Response
#### Success Response (any)
- Returns the value associated with the key, or the `defaultValue` if provided and the key is not found.
### Request Example
```js
views.get("list"); // ListComponent
views.get("kanban"); // throws OwlError
views.get("kanban", null); // returns null
```
```
--------------------------------
### Run Owl Devtools in Development Mode for Chrome
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/tools/devtools.md
Starts the Owl Devtools extension in development mode for Chrome, avoiding recompilation.
```bash
npm run dev:devtools-chrome
```
--------------------------------
### Provide App-Level Plugins
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/plugins.md
Pass an array of plugins to the `mount` function to make them available globally to all components.
```javascript
await mount(RootComponent, document.body, {
plugins: [NotificationManager, RouterPlugin],
});
```
--------------------------------
### Accessing Props in an Owl Component
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/props.md
Call the `props()` function within a component to get an object with getters for each prop. This object is assigned to `this.props`.
```js
import { Component, props, xml } from "@odoo/owl";
class MyComponent extends Component {
static template = xml``;
props = props();
}
```
--------------------------------
### Owl 3.x Event Handler Binding
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Example of an event handler in Owl 3.x, requiring 'this.' for explicit component method access.
```xml
...
```
--------------------------------
### Mounting an Owl Application
Source: https://github.com/odoo/owl/blob/master/tools/playground/static/tutorials.md
This is the standard way to mount a valid Owl application in the playground. Ensure the templates and dev options are correctly set.
```javascript
mount(Counter, document.body, { templates: TEMPLATES, dev: true });
```
--------------------------------
### Run Owl Release Script
Source: https://github.com/odoo/owl/wiki/Release-checklist
Executes the release script for Owl. Ensure a GitHub token is saved in .env.local if not already present.
```bash
npm run release
```
--------------------------------
### useEffect Hook in Components
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/effects.md
Demonstrates the usage of the `useEffect` hook within an Owl component's `setup` method, which is automatically cleaned up when the component is destroyed.
```javascript
class MyComponent extends Component {
static template = xml``;
setup() {
const value = signal(0);
// equivalent to: onWillDestroy(effect(() => { ... }))
useEffect(() => {
console.log(value());
});
}
}
```
--------------------------------
### Create and Mount an Owl Root
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/app.md
Demonstrates the basic creation, mounting, and destruction of an Owl root component. Ensure `root.destroy()` is called when the target element is removed from the DOM.
```javascript
const root = app.createRoot(MyComponent, { props: { someProps: true } });
await root.mount(targetElement);
// later
root.destroy();
```
--------------------------------
### Outputting Reactive Values (Current vs. Proposed)
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Illustrates the current method of outputting reactive values using function calls in templates, and a proposed, more magical syntax that was ultimately rejected due to complexity and potential issues.
```xml
```
```xml
```
--------------------------------
### Define a Computed Value in Owl
Source: https://github.com/odoo/owl/blob/master/tools/playground/samples/v3/tutorials/todo_list/9/readme.md
Use `computed` to create a reactive value that recalculates when its dependencies change. This example calculates the number of remaining todos.
```javascript
import { computed } from "@odoo/owl";
remaining = computed(() => {
return this.todos().filter((todo) => !todo.completed()).length;
});
```
--------------------------------
### Basic Effect Usage and Cleanup
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/effects.md
Demonstrates creating an effect that logs a computed value, how it re-runs after a microtask when a signal changes, and how to clean up the effect.
```javascript
const s = signal(3);
const d = computed(() => 2 * s());
const cleanup = effect(() => {
console.log(d()); // logs 6
});
s.set(4);
// nothing happens immediately
await Promise.resolve();
// now 8 is logged — the effect was re-executed
cleanup();
// the effect is now inactive
s.set(5);
await Promise.resolve();
// nothing happens
```
--------------------------------
### Define a Counter Component
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/component.md
Example of a basic Owl component that increments a counter on button click. Uses `xml` for templating and `signal` for reactive state.
```javascript
const { Component, xml, signal } = owl;
class Counter extends Component {
static template = xml`
`;
count = signal(0);
increment() {
this.count.set(this.count() + 1);
}
}
```
--------------------------------
### Handling Root Element References in Owl 2
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/migration_owl1_to_owl2.md
In Owl 2, component.el is removed. Use refs to get a reference to the root HTML element of a template.
```xml
... content ...
```
--------------------------------
### Implement Window Dragging Logic
Source: https://github.com/odoo/owl/blob/master/tools/playground/samples/v3/tutorials/hibou_os/10/readme.md
Implement the `startDrag` method to handle the dragging of windows. This involves recording initial mouse and window positions on `mousedown`, and updating the `x` and `y` signals on `mousemove`.
```js
startDrag(ev) {
const startX = ev.clientX;
const startY = ev.clientY;
const origX = this.props.x();
const origY = this.props.y();
const onMouseMove = (moveEv) => {
this.props.x.set(origX + moveEv.clientX - startX);
this.props.y.set(origY + moveEv.clientY - startY);
};
const onMouseUp = () => {
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", onMouseUp);
};
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
}
```
--------------------------------
### t-call Node Restriction
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
In Owl 3.x, t-call can only be used on nodes. Examples show the incorrect usage in Owl 2.x and the correct Owl 3.x approach.
```xml
```
--------------------------------
### Valid Fragment Template: Multiple Root Elements
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/template_syntax.md
Owl supports templates with multiple root elements. This example shows two div elements as siblings.
```xml
hello
ola
```
--------------------------------
### Owl 2.x App Mounting
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
In Owl 2.x, an App could be instantiated with a main component and then mounted directly.
```js
// owl 2.x
class SomeComponent extends Component { ... }
const app = new App(SomeComponent);
await app.mount(target, { props: someProps });
```
--------------------------------
### Basic Signal, Proxy, and Computed Usage
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
Demonstrates the basic usage of `signal`, `proxy`, and `computed` to create reactive values and derive new ones. `computed` values are lazily evaluated and recomputed when dependencies change.
```javascript
const count = signal(0);
const state = proxy({ color: "red", value: 15 });
const total = computed(() => count() + state.value);
console.log(total()); // logs 15
```
--------------------------------
### Set Plugin Startup Sequence
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/plugins.md
Use the `static sequence` property to control the startup order of plugins. Lower numbers indicate earlier startup.
```javascript
class SessionPlugin extends Plugin {
static sequence = 10; // foundational: starts before the others
setup() {
onWillStart(async () => {
this.user = await loadSession();
});
}
}
```
--------------------------------
### Multiple References with Resource
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/refs.md
Example of using `t-ref` with a Resource to manage multiple DOM elements, such as paragraphs within a loop. The resource's `items()` is reactive.
```xml
```
```javascript
class MyComponent extends Component {
items = signal([1, 2, 3]);
paragraphs = new Resource({ name: "paragraphs" });
get allParagraphs() {
return this.paragraphs.items(); // reactive list of
elements
}
}
```
--------------------------------
### Basic Proxy Usage
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/proxies.md
Demonstrates how to create a reactive proxy and access its properties. Nested objects are automatically proxied.
```javascript
const p = proxy({ a: { b: 3 }, c: 2 });
p.a; // returns a proxy for { b: 3 }
p.a.b; // returns 3, subscribes to both "a" and "b"
p.c; // returns 2, subscribes to "c"
```
--------------------------------
### Set Input Focus with t-ref
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/refs.md
Example of setting focus on an input element using a reference signal. The `t-ref` directive binds the signal to the DOM node.
```xml
```
```javascript
class SomeComponent extends Component {
inputRef = signal.ref();
focusInput() {
this.inputRef()?.focus();
}
}
```
--------------------------------
### Nested Effects and Ownership
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/reference/effects.md
Illustrates how effects created within other effects become children, with their lifetimes managed by the parent. Includes an example of implicit ownership and its consequences.
```javascript
effect(() => {
// parent
console.log("parent");
effect(() => {
// child, owned by parent
console.log(someSignal());
return () => console.log("child cleanup");
});
});
```
```javascript
let created = false;
effect(() => {
// B
someSignal();
if (!created) {
created = true;
effect(() => {
// A, created only once — but owned by B
otherSignal();
});
}
});
```
--------------------------------
### MyApp Component and Mounting
Source: https://github.com/odoo/owl/blob/master/doc/v3/owl/owl3_design.md
This snippet defines the main `MyApp` component, which includes the `Editor` and `Notification` components, and provides buttons to toggle the editor and add notifications. It also shows how to mount the application to the DOM with plugins.
```javascript
class MyApp extends Component {
static components = { Editor, Notification };
static template = xml`