or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

app-components.mdblockdom.mdhooks.mdindex.mdlifecycle.mdreactivity.mdtemplates.mdutils-validation.md

app-components.mddocs/

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

```