Skip to content

Commit 47e5510

Browse files
committed
[IMP] awesome_owl: Add counter and todolists components
Discover the web framework - Chapter 1 - Owl components
1 parent 9231b81 commit 47e5510

11 files changed

Lines changed: 188 additions & 3 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Component, useState } from "@odoo/owl";
2+
3+
export class Card extends Component {
4+
static template = "awesome_owl.Card";
5+
static props = {
6+
title: { type: String, required: true },
7+
slots: Object,
8+
}
9+
10+
setup() {
11+
this.state = useState({isOpened: false});
12+
}
13+
14+
expand() {
15+
this.state.isOpened = !this.state.isOpened;
16+
}
17+
}
18+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<templates xml:space="preserve">
3+
4+
<t t-name="awesome_owl.Card">
5+
<div class="card d-inline-block m-2" style="width: 18rem;">
6+
<div class="card-body">
7+
<h5 class="card-title">
8+
<t t-out="props.title"/>
9+
<button class="btn btn-primary" t-on-click="expand">
10+
<t t-if="state.isOpened">Collapse</t>
11+
<t t-if="!state.isOpened">Expand</t>
12+
</button>
13+
</h5>
14+
<p class="card-text" t-if="state.isOpened">
15+
<t t-slot="default"/>
16+
</p>
17+
</div>
18+
</div>
19+
</t>
20+
</templates>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Component, useState } from "@odoo/owl";
2+
3+
4+
export class Counter extends Component {
5+
static template = "awesome_owl.Counter";
6+
static props = {
7+
onChange: {type: Function, optional: true},
8+
}
9+
10+
setup() {
11+
this.state = useState({ value: 1 });
12+
}
13+
14+
increment() {
15+
this.state.value++;
16+
this.props.onChange?.();
17+
}
18+
}
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+
4+
<t t-name="awesome_owl.Counter">
5+
<div class="m-2 p-2 border d-inline-block">
6+
<span class="me-2">Counter: <t t-out="state.value"/></span>
7+
<button class="btn btn-primary" t-on-click="increment">Increment</button>
8+
</div>
9+
</t>
10+
11+
</templates>
Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
1-
import { Component } from "@odoo/owl";
1+
import { Component, markup, useState } from "@odoo/owl";
2+
import { Counter } from "./counter/counter";
3+
import { Card } from "./card/card";
4+
import { TodoList } from "./todo_list/todo_list";
25

36
export class Playground extends Component {
47
static template = "awesome_owl.playground";
8+
static components = { Counter, Card, TodoList };
9+
10+
setup() {
11+
this.value1 = "<div class='text-danger'>Hello</div>";
12+
this.value2 = markup("<img src='x' onerror='alert(1)'/>");
13+
this.sum = useState({ value: 2 });
14+
}
15+
16+
incrementSum() {
17+
this.sum.value++;
18+
}
519
}

awesome_owl/static/src/playground.xml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,21 @@
22
<templates xml:space="preserve">
33

44
<t t-name="awesome_owl.playground">
5-
<div class="p-3">
6-
hello world
5+
<div class="p-3 border d-inline-block">
6+
<Counter onChange.bind="this.incrementSum"/>
7+
<Counter onChange.bind="this.incrementSum"/>
8+
<p class="mt-2">Sum: <t t-out="sum.value"/></p>
79
</div>
10+
11+
<div>
12+
<Card title="'Card 1'">
13+
Card 1 content.
14+
</Card>
15+
<Card title="'Card 2'">
16+
<Counter/>
17+
</Card>
18+
</div>
19+
<TodoList/>
820
</t>
921

1022
</templates>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {Component} from "@odoo/owl";
2+
3+
export class TodoItem extends Component {
4+
static template = "awesome_owl.TodoItem";
5+
static props = {
6+
todo: {
7+
type: Object,
8+
shape: {
9+
id: Number,
10+
description: String,
11+
isCompleted: Boolean,
12+
}
13+
},
14+
toggleState: Function,
15+
removeTodo: Function,
16+
};
17+
18+
onChanged() {
19+
this.props.toggleState(this.props.todo.id);
20+
}
21+
22+
}
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.TodoItem">
4+
<div t-att-class="props.todo.isCompleted ? 'text-decoration-line-through' : ''">
5+
<input class="form-check-box" type="checkbox" t-att-checked="props.todo.isCompleted" t-on-change="onChanged"/>
6+
<t t-out="props.todo.id"/>.
7+
<t t-out="props.todo.description"/>
8+
<span class="fa fa-remove" t-on-click="() => props.removeTodo(props.todo.id)"/>
9+
</div>
10+
</t>
11+
</templates>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {Component, useState} from "@odoo/owl";
2+
import {TodoItem} from "./todo_item";
3+
import {useAutoFocus} from "../utils";
4+
5+
export class TodoList extends Component {
6+
static template = "awesome_owl.TodoList";
7+
static components = {TodoItem};
8+
9+
setup() {
10+
this.currId = 1;
11+
this.todos = useState([]);
12+
useAutoFocus("input_todo");
13+
}
14+
15+
addTodo(ev) {
16+
if (ev.keyCode === 13 && ev.target.value !== "") {
17+
this.todos.push({
18+
id: this.currId++,
19+
description: ev.target.value,
20+
isCompleted: false
21+
});
22+
ev.target.value = "";
23+
}
24+
}
25+
26+
toggleTodo(id) {
27+
const todo = this.todos.find(todo => todo.id === id);
28+
if (todo) {
29+
todo.isCompleted = !todo.isCompleted;
30+
}
31+
}
32+
33+
removeTodo(id) {
34+
const index = this.todos.findIndex(todo => todo.id === id);
35+
if (index >= 0) {
36+
this.todos.splice(index, 1);
37+
}
38+
}
39+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<templates xml:space="preserve">
3+
<t t-name="awesome_owl.TodoList">
4+
<div class="d-inline-block border p-2 m-2">
5+
<input class="form-control mb-3" type="text" placeholder="Add a todo !" t-on-keyup="addTodo" t-ref="input_todo"/>
6+
<p t-if="todos.length === 0">No todos yet !</p>
7+
<t t-foreach="todos" t-as="todo" t-key="todo.id">
8+
<TodoItem todo="todo" toggleState.bind="toggleTodo" removeTodo.bind="removeTodo"/>
9+
</t>
10+
</div>
11+
</t>
12+
</templates>

0 commit comments

Comments
 (0)