Skip to content

Commit def7352

Browse files
committed
[ADD] real_estate : Load demo data and implement Todo List component (Ch.1)
- Added XML demo data to preload sample records - Implemented Todo List component fully in JS - Completed Chapter 1 exercise as per OWL training
1 parent d052826 commit def7352

20 files changed

+271
-93
lines changed

awesome_owl/static/src/card/card.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@ export class Card extends Component {
55
static template = "awesome_owl.Card";
66
static props = {
77
title: { type: String },
8+
slots: { type: Object, optional: true },
89
content: { type: String, optional: true },
9-
content: String,
1010
};
11+
setup() {
12+
this.state = useState({ open: true });
13+
}
14+
15+
toggle() {
16+
this.state.open = !this.state.open;
17+
}
18+
1119
}
Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<templates xml:space="preserve">
3+
34
<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">
5+
<div class="card shadow-sm m-2" style="width: 20rem;">
6+
<div class="card-header d-flex justify-content-between align-items-center">
7+
<span class="fw-bold">
78
<t t-esc="props.title"/>
8-
</h5>
9-
<p class="card-text">
10-
<t t-out="props.content"/>
11-
</p>
9+
</span>
10+
11+
<button class="btn btn-sm btn-outline-secondary"
12+
t-on-click="toggle">
13+
<t t-if="state.open">−</t>
14+
<t t-else=""> + </t>
15+
</button>
1216
</div>
17+
<t t-if="state.open">
18+
<div class="card-body">
19+
<t t-slot="default"/>
20+
</div>
21+
</t>
1322
</div>
1423
</t>
24+
1525
</templates>

awesome_owl/static/src/counter/counter.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
/** @odoo-module **/
22
import { Component, useState} from "@odoo/owl";
33

4-
54
export class Counter extends Component {
65
static template = "awesome_owl.Counter";
76
static props = {
87
onChange: { type: Function, optional: true },
98
};
9+
1010
setup() {
1111
this.state = useState({ counter: 0 });
12+
// debugger;
1213
}
1314

1415
increment() {
Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,13 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<templates xml:space="preserve">
33
<t t-name="awesome_owl.Counter">
4-
<!-- <div class="o_counter">-->
5-
<!-- <h2>Counter Example</h2>-->
6-
<!-- <p>Current value: <t t-esc="state.counter"/></p>-->
7-
<!-- <button t-on-click="increment" class="btn btn-primary">Increment</button>-->
8-
9-
<div class="o_counter">
10-
<div class="card d-inline-block m-2" style="width: 18rem;">
11-
<div class="card-body d-flex justify-content-between align-items-center">
12-
<span class="fw-bold">
4+
<div class="d-flex justify-content-between align-items-center border rounded p-2">
5+
<span class="fw-semibold">
136
Counter: <t t-esc="state.counter"/>
147
</span>
15-
<button t-on-click="increment" class="btn btn-primary btn-sm">
16-
Increment
8+
<button t-on-click="increment" class="btn btn-sm btn-primary">
9+
+ Increment
1710
</button>
1811
</div>
19-
</div>
20-
</div>
2112
</t>
2213
</templates>

awesome_owl/static/src/playground.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,5 @@ export class Playground extends Component {
2626
this.state.sum = this.c1 + this.c2;
2727
}
2828

29-
// setup() {
30-
// this.state = useState({ counter: 0 });
31-
// }
32-
//
33-
// increment() {
34-
// this.state.counter += 1;
35-
// }
36-
3729
}
3830
//Playground.template = "awesome_owl.Playground";
Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,23 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<templates xml:space="preserve">
33
<t t-name="awesome_owl.Playground">
4-
<!-- <div class="o_playground">-->
5-
<div class="o_playground p-3">
6-
7-
<div class="d-flex">
8-
<Counter onChange.bind="onCounter1Change"/>
9-
<Counter onChange.bind="onCounter2Change"/>
10-
</div>
11-
12-
<p class="mt-2 fw-bold">
13-
The sum is: <t t-esc="state.sum"/>
14-
</p>
4+
<div class="o_playground p-4">
155

6+
<div class="d-flex gap-3 flex-wrap">
7+
<Card title="'First Card'">
8+
<Counter onChange.bind="onCounter1Change"/>
9+
</Card>
1610

17-
<Card title="'First Card'" content="safeHtml"/>
18-
<Card title="'Second Card'" content="unsafeHtml"/>
19-
<Card title="'Third card'" content="'Reusable components are powerful!'"/>
11+
<Card title="'Second Card'">
12+
<Counter onChange.bind="onCounter2Change"/>
13+
</Card>
14+
</div>
2015

21-
<!-- <h2>Counter Example</h2>-->
22-
<!-- <p>Current value: <t t-esc="state.counter"/></p>-->
23-
<!-- <button t-on-click="increment">Increment</button>-->
16+
<p class="mt-4 fs-5 fw-bold text-success">
17+
The sum is: <t t-esc="state.sum"/>
18+
</p>
2419

25-
<TodoList/>
20+
<TodoList/>
2621
</div>
2722
</t>
2823
</templates>

awesome_owl/static/src/todo/todo_item.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export class TodoItem extends Component {
77
static template = "awesome_owl.TodoItem";
88
static props = {
99
todo: { type: Object, required: true },
10+
toggleState: { type: Function, required: true },
11+
removeTodo: { type: Function, required: true },
1012
};
1113
}
12-

awesome_owl/static/src/todo/todo_item.xml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,23 @@
22
<templates xml:space="preserve">
33
<t t-name="awesome_owl.TodoItem">
44
<div>
5-
<span><t t-esc="props.todo.id"/> - <t t-esc="props.todo.description"/></span>
5+
<li class="list-group-item d-flex align-items-center justify-content-between"
6+
t-att-class="props.todo.isCompleted
7+
? 'text-muted text-decoration-line-through'
8+
: ''">
9+
<div>
10+
<input type="checkbox"
11+
class="form-check-input me-2"
12+
t-att-checked="props.todo.isCompleted"
13+
t-on-change="() => props.toggleState(props.todo.id)"/>
14+
15+
<t t-esc="props.todo.id"/>
16+
-
17+
<t t-esc="props.todo.description"/>
18+
</div>
19+
<span class="fa fa-remove text-danger cursor-pointer"
20+
t-on-click="() => props.removeTodo(props.todo.id)"/>
21+
</li>
622
</div>
723
</t>
824

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/** @odoo-module **/
2-
import { Component, useState } from "@odoo/owl";
2+
import { Component, useState, useRef, onMounted } from "@odoo/owl";
33
import { TodoItem } from "./todo_item";
44

55
export class TodoList extends Component {
@@ -8,12 +8,49 @@ export class TodoList extends Component {
88
static components = { TodoItem };
99

1010
setup() {
11-
this.state = useState({
12-
todos: [
13-
{ id: 1, description: "buy milk", isCompleted: false },
14-
{ id: 2, description: "write report", isCompleted: true },
15-
{ id: 3, description: "call friend", isCompleted: false },
16-
]
11+
// this.state = useState({
12+
// todos: [
13+
// { id: 1, description: "buy milk", isCompleted: false },
14+
// { id: 2, description: "write report", isCompleted: true },
15+
// { id: 3, description: "call friend", isCompleted: false },
16+
// ]
17+
// });
18+
this.state = useState({
19+
todos: [],
20+
nextId: 1,
21+
});
22+
this.inputRef = useRef("input");
23+
onMounted(() => {
24+
this.inputRef.el.focus();
1725
});
18-
}
26+
27+
}
28+
addTodo(ev) {
29+
if (ev.keyCode === 13) {
30+
const value = ev.target.value.trim();
31+
if (!value) {
32+
return;
33+
}
34+
this.state.todos.push({
35+
id: this.state.nextId++,
36+
description: value,
37+
isCompleted: false,
38+
});
39+
ev.target.value = "";
40+
}
41+
}
42+
43+
toggleTodo(id) {
44+
const todo = this.state.todos.find(t => t.id === id);
45+
if (todo) {
46+
todo.isCompleted = !todo.isCompleted;
47+
}
48+
}
49+
50+
removeTodo(id) {
51+
const index = this.state.todos.findIndex(t => t.id === id);
52+
if (index >= 0) {
53+
this.state.todos.splice(index, 1);
54+
}
55+
}
1956
}

awesome_owl/static/src/todo/todo_list.xml

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,20 @@
22
<templates xml:space="preserve">
33
<t t-name="awesome_owl.TodoList">
44
<div>
5-
<t t-foreach="state.todos" t-as="todo" t-key="todo.id">
6-
<TodoItem t-props='{"todo": todo}'/>
7-
</t>
5+
<!-- <t t-foreach="state.todos" t-as="todo" t-key="todo.id">-->
6+
<!-- <TodoItem t-props='{"todo": todo}'/>-->
7+
<!-- <TodoItem todo="todo"/>-->
8+
<!-- </t>-->
9+
<input class="form-control mb-2"
10+
placeholder="Enter a new task"
11+
t-ref="input"
12+
t-on-keyup="addTodo"/>
13+
14+
<ul class="list-group">
15+
<t t-foreach="state.todos" t-as="todo" t-key="todo.id">
16+
<TodoItem todo="todo" toggleState.bind="toggleTodo" removeTodo.bind="removeTodo"/>
17+
</t>
18+
</ul>
819
</div>
920
</t>
10-
11-
1221
</templates>

0 commit comments

Comments
 (0)