0
# Application & Components
1
2
Core application container and component system for creating and managing OWL applications with mounting, lifecycle, and component hierarchy.
3
4
## Capabilities
5
6
### App Class
7
8
The main application container that manages component lifecycle, mounting, and provides the template compilation environment.
9
10
```typescript { .api }
11
/**
12
* Main application container extending TemplateSet
13
* @template T - Component constructor type
14
* @template P - Props type
15
* @template E - Environment type
16
*/
17
class App<T, P, E> extends TemplateSet {
18
/** Application name */
19
name: string;
20
/** Root component constructor */
21
Root: ComponentConstructor<P, E>;
22
/** Application props */
23
props: P;
24
/** Application environment */
25
env: E;
26
/** Internal scheduler */
27
scheduler: Scheduler;
28
/** Set of sub-roots */
29
subRoots: Set<ComponentNode>;
30
/** Root component node */
31
root: ComponentNode<P, E> | null;
32
33
/** Static target validation utility */
34
static validateTarget(target: any): void;
35
/** Static set of all app instances */
36
static apps: Set<App>;
37
/** Static OWL version string */
38
static version: string;
39
40
/**
41
* Creates a new OWL application
42
* @param Root - Root component constructor
43
* @param config - Application configuration
44
*/
45
constructor(Root: ComponentConstructor<P, E>, config?: AppConfig<P, E>);
46
47
/**
48
* Mounts the application to a DOM target
49
* @param target - DOM element or shadow root to mount to
50
* @param options - Mount options
51
* @returns Promise resolving to the mounted component instance
52
*/
53
mount(target: HTMLElement | ShadowRoot, options?: MountOptions): Promise<Component<P, E>>;
54
55
/**
56
* Creates a sub-root component that can be independently mounted
57
* @template Props - Component props type
58
* @template SubEnv - Sub-environment type
59
* @param Root - Component constructor
60
* @param config - Root configuration
61
* @returns Root object with mount and destroy methods
62
*/
63
createRoot<Props, SubEnv>(
64
Root: ComponentConstructor<Props, SubEnv>,
65
config?: RootConfig<Props, SubEnv>
66
): Root<Props, SubEnv>;
67
68
/**
69
* Creates a component node
70
* @param Component - Component constructor
71
* @param props - Component props
72
* @returns New ComponentNode instance
73
*/
74
makeNode(Component: ComponentConstructor, props: any): ComponentNode;
75
}
76
```
77
78
**Usage Examples:**
79
80
```typescript
81
import { App, Component, xml } from "@odoo/owl";
82
83
class MyApp extends Component {
84
static template = xml`<div>Hello OWL!</div>`;
85
}
86
87
// Basic app creation and mounting
88
const app = new App(MyApp, {
89
name: "MyApplication",
90
dev: true
91
});
92
93
await app.mount(document.body);
94
95
// App with props and environment
96
const appWithConfig = new App(MyApp, {
97
props: { title: "My App" },
98
env: { apiUrl: "https://api.example.com" },
99
dev: process.env.NODE_ENV === "development"
100
});
101
102
await appWithConfig.mount(document.getElementById("app"));
103
104
// Creating sub-roots for micro-frontend patterns
105
const subRoot = app.createRoot(AnotherComponent, {
106
props: { mode: "embedded" },
107
env: { theme: "dark" }
108
});
109
110
await subRoot.mount(document.getElementById("widget"));
111
```
112
113
### Mount Function
114
115
Convenience function for quickly mounting a component without explicitly creating an App instance.
116
117
```typescript { .api }
118
/**
119
* Convenience function to mount a component directly
120
* @template T - Component constructor type
121
* @template P - Props type
122
* @template E - Environment type
123
* @param C - Component constructor to mount
124
* @param target - DOM element or shadow root to mount to
125
* @param config - Optional application configuration
126
* @returns Promise resolving to the mounted component instance
127
*/
128
function mount<T, P, E>(
129
C: ComponentConstructor<P, E>,
130
target: HTMLElement | ShadowRoot,
131
config?: AppConfig<P, E>
132
): Promise<Component<P, E>>;
133
```
134
135
**Usage Examples:**
136
137
```typescript
138
import { mount, Component, xml } from "@odoo/owl";
139
140
class QuickComponent extends Component {
141
static template = xml`<div>Quick mount!</div>`;
142
}
143
144
// Simple mounting
145
await mount(QuickComponent, document.body);
146
147
// Mount with configuration
148
await mount(QuickComponent, document.getElementById("app"), {
149
props: { message: "Hello" },
150
env: { user: currentUser },
151
dev: true
152
});
153
```
154
155
### Component Class
156
157
Base class for all OWL components providing lifecycle management, props handling, and rendering capabilities.
158
159
```typescript { .api }
160
/**
161
* Base component class for all OWL components
162
* @template Props - Component props type
163
* @template Env - Environment type
164
*/
165
class Component<Props = any, Env = any> {
166
/** Static template string (must be defined by subclasses) */
167
static template: string;
168
/** Static props validation schema */
169
static props?: Schema;
170
/** Static default props values */
171
static defaultProps?: any;
172
/** Static sub-components registry */
173
static components?: { [componentName: string]: ComponentConstructor };
174
175
/** Component props */
176
props: Props;
177
/** Component environment */
178
env: Env;
179
/** Internal OWL component node (do not use directly) */
180
__owl__: ComponentNode;
181
182
/**
183
* Component constructor (called by OWL framework)
184
* @param props - Component properties
185
* @param env - Component environment
186
* @param node - Internal component node
187
*/
188
constructor(props: Props, env: Env, node: ComponentNode);
189
190
/**
191
* Setup hook called during component initialization
192
* Use this for state initialization, hook setup, and other initialization logic
193
*/
194
setup(): void;
195
196
/**
197
* Triggers a re-render of this component
198
* @param deep - Whether to force deep re-render of all children
199
*/
200
render(deep?: boolean): void;
201
}
202
```
203
204
**Usage Examples:**
205
206
```typescript
207
import { Component, xml, useState, useEnv } from "@odoo/owl";
208
209
// Basic component with template
210
class SimpleGreeting extends Component {
211
static template = xml`
212
<div class="greeting">
213
<h1>Hello, <t t-esc="props.name"/>!</h1>
214
</div>
215
`;
216
}
217
218
// Component with state and lifecycle
219
class TodoList extends Component {
220
static template = xml`
221
<div class="todo-list">
222
<input t-model="state.newTodo" t-on-keyup.enter="addTodo"/>
223
<ul>
224
<li t-foreach="state.todos" t-as="todo" t-key="todo.id">
225
<t t-esc="todo.text"/>
226
</li>
227
</ul>
228
</div>
229
`;
230
231
setup() {
232
this.state = useState({
233
todos: [],
234
newTodo: ""
235
});
236
}
237
238
addTodo() {
239
if (this.state.newTodo.trim()) {
240
this.state.todos.push({
241
id: Date.now(),
242
text: this.state.newTodo.trim()
243
});
244
this.state.newTodo = "";
245
}
246
}
247
}
248
249
// Component with props validation and environment usage
250
class UserProfile extends Component {
251
static template = xml`
252
<div class="user-profile">
253
<h2><t t-esc="props.user.name"/></h2>
254
<p><t t-esc="props.user.email"/></p>
255
<button t-if="env.isAdmin" t-on-click="editUser">Edit</button>
256
</div>
257
`;
258
259
static props = {
260
user: {
261
type: Object,
262
shape: {
263
name: String,
264
email: String,
265
id: Number
266
}
267
}
268
};
269
270
setup() {
271
this.env = useEnv();
272
}
273
274
editUser() {
275
console.log("Editing user:", this.props.user.id);
276
}
277
}
278
```
279
280
### Configuration Types
281
282
```typescript { .api }
283
interface AppConfig<P, E> extends TemplateSetConfig, RootConfig<P, E> {
284
/** Application name for debugging */
285
name?: string;
286
/** Enable test mode */
287
test?: boolean;
288
/** Warn if components don't have static props */
289
warnIfNoStaticProps?: boolean;
290
}
291
292
interface RootConfig<P, E> {
293
/** Props to pass to root component */
294
props?: P;
295
/** Environment to provide to components */
296
env?: E;
297
}
298
299
interface MountOptions {
300
/** Where to position the component in the target */
301
position?: "first-child" | "last-child";
302
}
303
304
interface Root<P, E> {
305
/** Component node reference */
306
node: ComponentNode<P, E>;
307
/** Mount the root to a DOM target */
308
mount(target: HTMLElement | ShadowRoot, options?: MountOptions): Promise<Component<P, E>>;
309
/** Destroy the root and clean up */
310
destroy(): void;
311
}
312
```