Odoo Web Library (OWL) is a modern, lightweight TypeScript UI framework for building reactive web applications with components, templates, and state management.
npx @tessl/cli install tessl/npm-odoo--owl@2.8.0OWL is a modern, lightweight TypeScript UI framework built by Odoo for creating reactive web applications. It combines the best ideas from React and Vue in a simple and consistent way, featuring declarative components with ES6 classes and XML templates, fine-grained reactivity, hooks, and virtual DOM rendering.
npm install @odoo/owlimport { App, Component, mount, xml } from "@odoo/owl";For CommonJS:
const { App, Component, mount, xml } = require("@odoo/owl");import { App, Component, xml, useState } from "@odoo/owl";
class Counter extends Component {
static template = xml`
<div>
<p>Count: <t t-esc="state.count"/></p>
<button t-on-click="increment">+</button>
<button t-on-click="decrement">-</button>
</div>
`;
setup() {
this.state = useState({ count: 0 });
}
increment() {
this.state.count++;
}
decrement() {
this.state.count--;
}
}
const app = new App(Counter);
app.mount(document.body);OWL is built around several key components:
Core application container and component system for creating and managing OWL applications with mounting, lifecycle, and component hierarchy.
class App<T, P, E> {
constructor(Root: ComponentConstructor<P, E>, config?: AppConfig<P, E>);
mount(target: HTMLElement | ShadowRoot, options?: { position?: "first-child" | "last-child" }): Promise<Component<P, E>>;
}
function mount<P, E>(
C: ComponentConstructor<P, E>,
target: HTMLElement | ShadowRoot,
config?: AppConfig<P, E>
): Promise<Component<P, E>>;
class Component<Props = any, Env = any> {
static template: string;
static props?: Schema;
static defaultProps?: any;
constructor(props: Props, env: Env, node: ComponentNode);
setup(): void;
render(deep?: boolean): void;
}Hook functions for component state management, lifecycle integration, and accessing component context and environment.
function useState<T>(state: T): T;
function useComponent(): Component;
function useRef<T extends HTMLElement>(name: string): { el: T | null };
function useEnv<E>(): E;
function useSubEnv(envExtension: Env): void;
function useChildSubEnv(envExtension: Env): void;
function useEffect<T extends unknown[]>(
effect: (...dependencies: T) => void | (() => void),
computeDependencies?: () => [...T]
): void;
function useExternalListener(
target: EventTarget,
eventName: string,
handler: EventListener,
eventParams?: AddEventListenerOptions
): void;Component lifecycle management hooks for handling mounting, updating, rendering, and cleanup operations.
function onWillStart(callback: () => void | Promise<void>): void;
function onMounted(callback: () => void): void;
function onWillUpdateProps(callback: (nextProps: any) => void | Promise<void>): void;
function onWillRender(callback: () => void): void;
function onRendered(callback: () => void): void;
function onWillPatch(callback: () => void): void;
function onPatched(callback: () => void): void;
function onWillUnmount(callback: () => void): void;
function onWillDestroy(callback: () => void): void;
function onError(callback: (error: Error) => void): void;Fine-grained reactivity system for creating reactive state with automatic UI updates and change tracking.
function reactive<T extends object>(target: T): T;
function markRaw<T extends object>(target: T): T;
function toRaw<T>(observed: T): T;XML-based template system with compilation, runtime evaluation, and template management for component rendering.
function xml(...args: Parameters<typeof String.raw>): string;Virtual DOM implementation with block-based rendering, patching, and lifecycle management optimized for template-driven UIs.
const blockDom: {
mount: (vnode: VNode, fixture: HTMLElement, afterNode?: Node) => void;
patch: (vnode1: VNode, vnode2: VNode, withBeforeRemove?: boolean) => void;
remove: (vnode: VNode, withBeforeRemove?: boolean) => void;
list: (items: any[], template: Function) => VNode;
multi: (blocks: VNode[]) => VNode;
text: (value: string) => VNode;
comment: (value: string) => VNode;
toggler: (condition: boolean, template: Function) => VNode;
createBlock: (template: Function) => VNode;
html: (htmlString: string) => VNode;
};Utility functions for event handling, DOM manipulation, data loading, and component validation.
function batched(callback: () => void): () => void;
class EventBus extends EventTarget {
trigger(name: string, payload?: any): void;
}
function htmlEscape(str: string): string;
function whenReady(callback: Function): void;
function loadFile(url: string): Promise<string>;
function markup(template: TemplateStringsArray, ...args: any[]): string;
function validate(obj: { [key: string]: any }, spec: Schema): void;
function validateType(key: string, value: any, descr: TypeDescription): string | null;Component status checking utilities for debugging and lifecycle management.
function status(component: Component): "new" | "mounted" | "cancelled" | "destroyed";Runtime information about the OWL framework version and metadata.
const __info__: {
version: string;
};interface ComponentConstructor<P extends Props = any, E = any> {
new (props: P, env: E, node: ComponentNode): Component<P, E>;
template: string;
defaultProps?: any;
props?: Schema;
components?: { [componentName: string]: ComponentConstructor };
}
type Props = { [key: string]: any };
interface Env {
[key: string]: any;
}
interface AppConfig<P, E> {
name?: string;
test?: boolean;
warnIfNoStaticProps?: boolean;
props?: P;
env?: E;
dev?: boolean;
translatableAttributes?: string[];
translateFn?: (s: string, translationCtx: string) => string;
templates?: string | Document | Record<string, string>;
getTemplate?: (s: string) => Element | Function | string | void;
}type Template = (context: any, vnode: any, key?: string) => BDom;interface VNode<T = any> {
mount(parent: HTMLElement, afterNode: Node | null): void;
moveBeforeDOMNode(node: Node | null, parent?: HTMLElement): void;
moveBeforeVNode(other: T | null, afterNode: Node | null): void;
patch(other: T, withBeforeRemove: boolean): void;
beforeRemove(): void;
remove(): void;
firstNode(): Node | undefined;
el?: HTMLElement | Text;
parentEl?: HTMLElement;
isOnlyChild?: boolean;
key?: any;
}
type BDom = VNode<any>;type Schema = string[] | { [key: string]: TypeDescription };
type TypeDescription = BaseType | TypeInfo | ValueType | TypeDescription[];
type BaseType = { new (...args: any[]): any } | true | "*";
interface TypeInfo {
type?: TypeDescription;
optional?: boolean;
validate?: Function;
shape?: Schema;
element?: TypeDescription;
values?: TypeDescription;
}class OwlError extends Error {
cause?: any;
}