Skip to content

Commit 2f6fde4

Browse files
committed
[ADD] introduce to owl js: learn and build simple reactive components using owl
implemented counter component , that passed as slot in parent component card. build a todo list working app with CRUD oprations.
1 parent 2b8c3fb commit 2f6fde4

File tree

10 files changed

+187
-4
lines changed

10 files changed

+187
-4
lines changed

awesome_owl/static/src/card.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Component , useState } from "@odoo/owl";
2+
3+
export class Card extends Component {
4+
static template = "awesome_owl.card";
5+
6+
static components = { }
7+
8+
setup(){
9+
this.showCardContent = useState({value:true});
10+
}
11+
12+
toggleCardContent(){
13+
this.showCardContent.value = !this.showCardContent.value;
14+
}
15+
}

awesome_owl/static/src/card.xml

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 mt-4">
6+
<div class="card-header d-flex justify-content-between align-items-center">
7+
<h4 class="header-title mb-0">
8+
<t t-slot="card-title"/>
9+
</h4>
10+
<span class="fa cursor-pointer" t-att-class="showCardContent.value ? 'fa-chevron-up': 'fa-chevron-down'" t-on-click="toggleCardContent"></span>
11+
</div>
12+
13+
<div class="card-body" t-att-class="showCardContent.value ? 'd-flex' : 'd-none'">
14+
<t t-slot="card-content"/>
15+
</div>
16+
17+
</div>
18+
</t>
19+
20+
</templates>

awesome_owl/static/src/counter.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/** @odoo-module **/
2+
3+
import { Component , useState } from "@odoo/owl";
4+
5+
export class Counter extends Component {
6+
static template = "awesome_owl.counter";
7+
8+
static props = ['btnIndex','onchange']
9+
10+
setup(){
11+
this.count = useState({value:0});
12+
}
13+
14+
do_maths(){
15+
this.count.value++;
16+
this.props.onchange();
17+
}
18+
}

awesome_owl/static/src/counter.xml

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.counter">
4+
<div class="p-3">
5+
<p class="mb-1 ms-1 h5">Counter<t t-out="props.btnIndex"/>: <span class="h4 ms-2"><t t-out="count.value"/></span></p>
6+
<button class="btn border bg-primary text-white" t-on-click="do_maths">
7+
Increment
8+
</button>
9+
</div>
10+
</t>
11+
</templates>
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
/** @odoo-module **/
22

3-
import { Component } from "@odoo/owl";
3+
import { Component , useState } from "@odoo/owl";
4+
import { Counter } from "./counter";
5+
import { TodoList } from "./todo/todo_list";
6+
import { Card } from "./card";
47

58
export class Playground extends Component {
69
static template = "awesome_owl.playground";
10+
11+
static components = { Counter ,TodoList , Card}
12+
13+
setup(){
14+
this.sum = useState({value:0})
15+
}
16+
17+
increment(){
18+
this.sum.value++;
19+
}
720
}
Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
1-
<?xml version="1.0" encoding="UTF-8" ?>
1+
<?xml version="1.0" encoding="UTF-8"?>
22
<templates xml:space="preserve">
33

44
<t t-name="awesome_owl.playground">
55
<div class="p-3">
6-
hello world
6+
<h1>Sum is <t t-out="sum.value"/></h1>
7+
8+
<Card>
9+
<t t-set-slot="card-title">
10+
Counters
11+
</t>
12+
<t t-set-slot="card-content">
13+
<Counter btnIndex="1" onchange.bind="increment"/>
14+
<Counter btnIndex="2" onchange.bind="increment"/>
15+
</t>
16+
</Card>
17+
<Card>
18+
<t t-set-slot="card-title">
19+
Todo list
20+
</t>
21+
<t t-set-slot="card-content">
22+
<TodoList/>
23+
</t>
24+
</Card>
725
</div>
826
</t>
927

10-
</templates>
28+
</templates>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Component , useState } from "@odoo/owl";
2+
3+
export class TodoItem extends Component {
4+
static template = "awesome_owl.todo_item";
5+
6+
static components = { }
7+
8+
static props = ['todo','toggleState','removeItem']
9+
10+
setup(){
11+
}
12+
}
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.todo_item">
4+
<div class="border rounded p-3 d-flex align-items-center gap-2 mt-2" style="font-size:24px;">
5+
<input type="checkbox" class="cursor-pointer" t-att-checked="props.todo.isCompleted" t-on-change="()=> props.toggleState(props.todo.id)"/>
6+
<b t-out="props.todo.id + '.'" />
7+
<p class="mb-0" t-att-class="props.todo.isCompleted ? 'text-muted text-decoration-line-through':''" t-out="props.todo.description"/>
8+
<span class="fa fa-remove text-danger ms-3 cursor-pointer" t-on-click="()=> props.removeItem(props.todo.id)"/>
9+
</div>
10+
</t>
11+
</templates>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { Component , useState , useRef , onMounted } from "@odoo/owl";
2+
import { TodoItem } from "./todo_item";
3+
4+
function useAutoFocus(refName){
5+
let inputRef = useRef(refName);
6+
onMounted(()=>{
7+
inputRef.el.focus()
8+
})
9+
}
10+
11+
export class TodoList extends Component {
12+
static template = "awesome_owl.todo_list";
13+
14+
static components = { TodoItem }
15+
16+
setup(){
17+
this.todos = useState([]);
18+
this.idCount = 1;
19+
20+
useAutoFocus('todo_input');
21+
}
22+
23+
addTodo(e){
24+
const value = e.target.value;
25+
if(value){
26+
if(e.key === "Enter"){
27+
28+
this.todos.unshift({
29+
id:this.idCount++,
30+
description:value,
31+
isCompleted:false
32+
});
33+
34+
e.target.value = ""
35+
}
36+
}
37+
38+
}
39+
40+
removeItem(id){
41+
const itmIndex = this.todos.findIndex( itm => itm.id == id);
42+
if(itmIndex+1){
43+
this.todos.splice(itmIndex,1);
44+
}
45+
}
46+
47+
toggleState(id){
48+
const item = this.todos.find( x => x.id == id);
49+
if(item){
50+
item.isCompleted = !item.isCompleted;
51+
}
52+
}
53+
}
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.todo_list">
4+
<div class="p-3 w-100">
5+
<h3 class="mb-4 text-center">Todo items</h3>
6+
<input t-ref="todo_input" placeholder="Enter a new task" class="w-100 p-2 rounded border border-success" t-on-keyup="addTodo"/>
7+
<t t-foreach="todos" t-as="todo" t-key="todo.id">
8+
<TodoItem todo="todo" toggleState.bind="toggleState" removeItem.bind="removeItem"/>
9+
</t>
10+
</div>
11+
</t>
12+
</templates>

0 commit comments

Comments
 (0)