Skip to content

Commit b229be4

Browse files
committed
[IMP] awesome_owl: complete chapter 1 up to section 8 of Owl tutorial
- Implement basic Owl components and setup as per official tutorial - Add Counter component with reactive state management - Configure assets bundle and QWeb templates for frontend rendering - Setup route and controller for standalone Owl playground - Follow tutorial steps for mounting and updating components dynamically This commit reflects learning and code progress from https://www.odoo.com/documentation/18.0/developer/tutorials/discover_js_framework/01_owl_components.html#section-8
1 parent 9ac4d89 commit b229be4

File tree

13 files changed

+230
-18
lines changed

13 files changed

+230
-18
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Component, markup } from '@odoo/owl'
2+
3+
export class Card extends Component {
4+
static template = "awesome_owl.Card"
5+
static components = {}
6+
static props = {
7+
title: { type: String, default: "Card Title" },
8+
body: { type: String, default: "Card Body" },
9+
visit: { type: String, default: "Visit us", optional: true }
10+
}
11+
12+
setup() {
13+
super.setup();
14+
this.markup_visit = markup(this.props.visit)
15+
}
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<template xml:space="preserve">
3+
<t t-name="awesome_owl.Card">
4+
<div class="card d-inline-block m-2" style="width: 18rem;">
5+
<div class="card-body">
6+
<h5 class="card-title"><t t-esc="props.title"/></h5>
7+
<p class="card-text">
8+
<t t-esc="props.body"/>
9+
</p>
10+
<t t-if="props.visit">
11+
<t t-out="markup_visit"></t>
12+
</t>
13+
</div>
14+
</div>
15+
</t>
16+
</template>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Component, useState } from "@odoo/owl";
2+
3+
export class Counter extends Component {
4+
5+
static template = "awesome_owl.Counter";
6+
static components = {}
7+
static props = {
8+
onChange: {
9+
type: Function,
10+
optional: true
11+
}
12+
}
13+
14+
setup() {
15+
super.setup();
16+
this.state = useState({ value: 1 })
17+
}
18+
19+
increment() {
20+
this.state.value++;
21+
this.props.onChange?.(this.state.value);
22+
}
23+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<template xml:space="preserve">
3+
<t t-name="awesome_owl.Counter">
4+
<div class="card shadow-sm">
5+
<div class="card-body">
6+
<h2 class="card-title">Counter</h2>
7+
<div class="d-flex" style="align-items: center; justify-content: space-between">
8+
<button class="btn btn-success" t-on-click="increment" style="background-color: 'blue'">Increment</button>
9+
<p class="card-text">Value: <t t-esc="state.value"/></p>
10+
</div>
11+
</div>
12+
</div>
13+
</t>
14+
</template>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/** @odoo-module **/
2+
3+
import { Component, useState, useEffect } from "@odoo/owl";
4+
import { Counter } from "../counter/counter";
5+
import { Card } from "../card/card";
6+
import { TodoList } from "../todo/todolist/todolist";
7+
8+
export class Playground extends Component {
9+
static template = "awesome_owl.playground";
10+
static components = { Counter, Card, TodoList }
11+
static props = {}
12+
13+
setup() {
14+
this.state = useState({ counters: 2, sum: 0 });
15+
16+
useEffect(() => {
17+
this.state.sum = this.state.counters;
18+
},()=>[this.state.counters]);
19+
20+
this.cards = [
21+
{
22+
title: "Discover the Stars",
23+
body: "Explore the mysteries of the universe and learn about constellations and galaxies.",
24+
visit: "<a href='https://nasa.gov' target='_blank'>https://nasa.gov</a>"
25+
},
26+
{
27+
title: "Healthy Living Tips",
28+
body: "Simple and effective ways to improve your health and boost your energy every day.",
29+
visit: "<a href='https://www.healthline.com' target='_blank'>https://www.healthline.com</a>"
30+
},
31+
{
32+
title: "Travel on a Budget",
33+
body: "Find out how to see the world without breaking the bank — travel smart and save money.",
34+
visit: "<a href='https://www.nomadicmatt.com' target='_blank'>https://www.nomadicmatt.com</a>"
35+
},
36+
{
37+
title: "Mastering JavaScript",
38+
body: "Step-by-step guide to becoming proficient in JavaScript and building dynamic web apps.",
39+
visit: "<a href='https://javascript.info' target='_blank'>https://javascript.info</a>"
40+
},
41+
{
42+
title: "Cooking Made Easy",
43+
body: "Delicious and quick recipes for busy people who love home-cooked meals.",
44+
visit: "<a href='https://www.budgetbytes.com' target='_blank'>https://www.budgetbytes.com</a>"
45+
},
46+
{
47+
title: "Mindfulness & Meditation",
48+
body: "Learn techniques to reduce stress and enhance your mental wellbeing through mindfulness.",
49+
visit: "<a href='https://www.headspace.com' target='_blank'>https://www.headspace.com</a>"
50+
}
51+
];
52+
}
53+
54+
incrementSum() {
55+
this.state.sum++;
56+
57+
}
58+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<templates xml:space="preserve">
3+
4+
<t t-name="awesome_owl.playground">
5+
<div class="container mt-4 col-6">
6+
<div>
7+
<div class="d-flex gap-5" style="justify-content: space-between; flex-wrap: wrap">
8+
<t t-foreach="Array(state.counters)" t-as="counter" t-key="counter_index">
9+
<div class="col-5">
10+
<Counter onChange.bind="incrementSum"/>
11+
</div>
12+
</t>
13+
</div>
14+
<div class="text-center mt-3">
15+
<h2>Total: <t t-esc="state.sum"/></h2>
16+
</div>
17+
</div>
18+
19+
<!-- Card -->
20+
<div class="mt-4">
21+
<h2>Card Components</h2>
22+
<t t-foreach="cards" t-as="card" t-key="card_index">
23+
<Card t-props="card_value"/>
24+
</t>
25+
</div>
26+
27+
<!-- Todo -->
28+
<div class="mt-4 mb-4">
29+
<TodoList/>
30+
</div>
31+
</div>
32+
</t>
33+
</templates>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Component, useState } from "@odoo/owl"
2+
import { Card } from "../../card/card"
3+
4+
export class TodoItem extends Component {
5+
static template = "awesome_owl.todoitem"
6+
static components = { Card }
7+
static props = {
8+
id: { type: Number },
9+
description: { type: String },
10+
isCompleted: { type: Boolean, default: false }
11+
}
12+
13+
setup() {
14+
this.state = useState({
15+
todo: {
16+
id: String(this.props.id),
17+
description: this.props.description,
18+
isCompleted: this.props.isCompleted
19+
}
20+
})
21+
}
22+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<templates xml:space="preserve">
3+
<t t-name="awesome_owl.todoitem">
4+
<div class="card d-inline-block m-2" style="width: 18rem;" t-att-class="{'text-muted': !state.todo.isCompleted, 'text-decoration-line-through': !state.todo.isCompleted, 'bg-body-tertiary': !state.todo.isCompleted, 'text-body-tertiary': !state.todo.isCompleted}">
5+
<div class="card-body">
6+
<h3 class="card-title">
7+
<t t-esc="state.todo.id"/>
8+
</h3>
9+
<p class="card-text">
10+
<t t-esc="state.todo.description"/>
11+
</p>
12+
</div>
13+
</div>
14+
</t>
15+
</templates>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Component, useState } from "@odoo/owl"
2+
import { TodoItem } from "../todoitem/todoitem";
3+
4+
export class TodoList extends Component {
5+
static template = "awesome_owl.todolist"
6+
static components = { TodoItem }
7+
static props = {}
8+
9+
setup() {
10+
this.todos = useState([
11+
{ id: 1, description: "Buy milk", isCompleted: false },
12+
{ id: 2, description: "Walk the dog", isCompleted: true },
13+
{ id: 3, description: "Write blog post", isCompleted: false },
14+
{ id: 4, description: "Call mom", isCompleted: true },
15+
{ id: 5, description: "Clean the house", isCompleted: false },
16+
{ id: 6, description: "Pay bills", isCompleted: false },
17+
{ id: 7, description: "Read a book", isCompleted: true },
18+
{ id: 8, description: "Exercise", isCompleted: false }
19+
]);
20+
}
21+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<templates xml:space="preserve">
3+
<t t-name="awesome_owl.todolist">
4+
<h2>
5+
Todo List
6+
</h2>
7+
<t t-foreach="todos" t-as="todo" t-key="todo.id">
8+
<TodoItem t-props="todo_value"/>
9+
</t>
10+
</t>
11+
</templates>

0 commit comments

Comments
 (0)