### 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`
Count:
`; props = props({ count: t.signal(t.number()) }); increment() { this.props.count.set(this.props.count() + 1); } } class Root extends Component { static components = { Counter }; static template = xml`

Current sum:

`; 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`
portal content
`; } class Something 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 ``` -------------------------------- ### 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`
`; notifications = plugin(NotificationPlugin); isEditorVisible = signal(true); toggleEditor() { this.isEditorVisible.set(!this.isEditorVisible()); } addNotification() { this.notifications.add("Coucou", "Some text"); } } mount(MyApp, document.body, { plugins: [NotificationPlugin] }); ```