Skip to content

Commit 26ae352

Browse files
committed
[ADD] awesome_owl: build initial owl components with examples
- Built reusable Counter component with state and event handling - Created Card component supporting title, content, HTML markup, and slots - Displayed sum of counters using callback props - Developed dynamic TodoList and TodoItem with add, toggle, and delete functionality - Added conditional styling for completed todos - Implemented toggle button to show/hide card content
1 parent 992658e commit 26ae352

File tree

16 files changed

+289
-5
lines changed

16 files changed

+289
-5
lines changed

awesome_owl/static/src/card/card.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { useState, Component, xml, markup } from "@odoo/owl"
2+
3+
export class Card extends Component {
4+
static template = 'awesome_owl.card'
5+
6+
static props = {
7+
title: String,
8+
slots: {
9+
type: Object,
10+
shape: {
11+
default: Object
12+
},
13+
optional: true
14+
}
15+
};
16+
17+
setup() {
18+
this.html = "<div class='text-primary'>some content</div>"
19+
this.state = useState({
20+
title: "",
21+
content: "",
22+
toggle: false
23+
})
24+
this.value1 = markup(this.html)
25+
this.handleToggle = this.handleToggle.bind(this)
26+
}
27+
28+
handleToggle() {
29+
this.state.toggle = !this.state.toggle
30+
}
31+
32+
}

awesome_owl/static/src/card/card.xml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<templates xml:space="preserve">
4+
5+
<t t-name="awesome_owl.card">
6+
<div class="card d-inline-block m-2" style="width: 20rem">
7+
<div class="card-body">
8+
9+
<div class="d-flex justify-content-between">
10+
<h5 class="card-title">
11+
<t t-esc="props.title" />
12+
</h5>
13+
<span class="text-sm text-primary cursor-pointer" t-on-click="this.handleToggle">Toggle</span>
14+
</div>
15+
16+
<t t-if="this.state.toggle == false">
17+
<t t-slot="default" />
18+
</t>
19+
20+
</div>
21+
22+
</div>
23+
</t>
24+
25+
</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+
3+
4+
export class Counter extends Component {
5+
6+
static template = 'awesome_owl.counter';
7+
8+
setup() {
9+
this.state = useState({ value: 0 })
10+
}
11+
12+
increment() {
13+
this.state.value++
14+
this.props.onChange(1)
15+
}
16+
17+
decrement() {
18+
if (this.state.value >= 0) {
19+
this.state.value--
20+
}
21+
}
22+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<templates xml:space="preserve">
4+
5+
<t t-name="awesome_owl.counter">
6+
<div class="rounded-3 p-4" style="background-color: #dadada">
7+
<p>
8+
<strong>
9+
<t t-esc="props.name" />
10+
: </strong>
11+
<t t-if="state.value &lt; 0">
12+
<p class="text-danger">value cannot be less that zero</p>
13+
</t>
14+
<t t-else="">
15+
<t t-esc="state.value" />
16+
</t>
17+
</p>
18+
<br />
19+
<div class="d-flex gap-3">
20+
<button class="btn bg-primary text-white" t-on-click="increment">Increment</button>
21+
<button class="btn bg-secondary text-white" t-on-click="decrement">Decrement</button>
22+
</div>
23+
</div>
24+
</t>
25+
26+
</templates>

awesome_owl/static/src/playground.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
11
/** @odoo-module **/
22

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

58
export class Playground extends Component {
69
static template = "awesome_owl.playground";
10+
static components = { Counter, Card, TodoList }
11+
12+
setup(){
13+
this.state = useState({
14+
sum: 0
15+
})
16+
this.onChange = this.onChange.bind(this)
17+
}
18+
19+
onChange(value){
20+
this.state.sum = this.state.sum + value
21+
}
722
}

awesome_owl/static/src/playground.xml

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

44
<t t-name="awesome_owl.playground">
5-
<div class="p-3">
6-
hello world
5+
6+
<!-- Counters Section -->
7+
<div class="container border-bottom mb-4 pb-4">
8+
<h1 class="pb-3">
9+
<strong>Counters</strong>
10+
</h1>
11+
<h1 class="pb-3">
12+
<strong>Sum : <t t-esc="state.sum" /></strong>
13+
</h1>
14+
<div class="row g-4 p-3">
15+
<div class="col-lg-4">
16+
<Counter name="'Counter 1'" onChange="onChange" />
17+
</div>
18+
<div class="col-lg-4">
19+
<Counter name="'Counter 2'" onChange="onChange" />
20+
</div>
21+
</div>
22+
</div>
23+
24+
<!-- Cards Section -->
25+
<div class="border-bottom mb-4 pb-4 container">
26+
<h1 class="pb-3">
27+
<strong>Cards</strong>
28+
</h1>
29+
<Card title="'Counter Slot Card'">
30+
<Counter name="'Counter 3'" onChange="onChange" />
31+
</Card>
32+
</div>
33+
34+
35+
<!-- Todos Section -->
36+
<div class="container border-bottom mb-4 pb-4">
37+
<h1 class="pb-3">
38+
<strong>Todos</strong>
39+
</h1>
40+
<TodoList />
741
</div>
842
</t>
943

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Component } from "@odoo/owl"
2+
3+
export class TodoItem extends Component {
4+
static template = "awesome_owl.todo_item"
5+
6+
static props = {
7+
data: {
8+
id: { type: Number },
9+
description: { type: String },
10+
isCompleted: { type: Boolean }
11+
},
12+
toggleState: Function,
13+
removeTodo: Function,
14+
}
15+
16+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<templates xml:space="preserve">
4+
5+
<t t-name="awesome_owl.todo_item">
6+
<p t-att-class="{'text-muted text-decoration-line-through' : props.data.isCompleted}">
7+
<input type="checkbox" t-att-checked="props.data.isCompleted" class="me-2" t-on-change="() => props.toggleState(props.data.id)" />
8+
<t t-esc="props.data.id"/>
9+
.
10+
<span class="me-2">
11+
<t t-esc="props.data.description"/>
12+
</span>
13+
<span class="fa fa-trash text-danger ms-1 d-inline-block" t-on-click="() => props.removeTodo(props.data.id)"></span>
14+
</p>
15+
</t>
16+
17+
</templates>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { useState, Component, useRef } 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.todo_list"
7+
8+
setup() {
9+
this.inputRef = useRef('inputRef')
10+
this.state = useState([{
11+
id: 0,
12+
isCompleted: true,
13+
description: "test description"
14+
}]);
15+
16+
useAutoFocus(this.inputRef)
17+
this.toggleState = this.toggleState.bind(this)
18+
this.removeTodo = this.removeTodo.bind(this)
19+
this.current_id = 1
20+
}
21+
22+
addTodo(e) {
23+
if (e.keyCode === 13 && e.target.value !== "") {
24+
this.state.unshift({
25+
id: this.current_id,
26+
description: e.target.value,
27+
isCompleted: false
28+
})
29+
this.inputRef.el.value = ""
30+
this.current_id++
31+
}
32+
}
33+
34+
removeTodo(id) {
35+
const index = this.state.findIndex((elem) => elem.id === id);
36+
if (index >= 0) {
37+
this.state.splice(index, 1);
38+
}
39+
}
40+
41+
toggleState(id) {
42+
const current_todo = this.state.find((todo) => todo.id == id)
43+
if (current_todo) {
44+
current_todo.isCompleted = !current_todo.isCompleted
45+
}
46+
}
47+
48+
static components = { TodoItem }
49+
}
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+
3+
<templates xml:space="preserve">
4+
5+
<t t-name="awesome_owl.todo_list">
6+
<div class="card d-inline-block m-2 p-2">
7+
<input placeholder="Enter a new task" class="form-control" type="text" t-on-keyup="addTodo" t-ref="inputRef" />
8+
<div class="card-body">
9+
<t t-foreach="state" t-as="todo" t-key="todo.id">
10+
<TodoItem data="todo" toggleState="toggleState" removeTodo="removeTodo" />
11+
</t>
12+
</div>
13+
</div>
14+
</t>
15+
16+
</templates>

0 commit comments

Comments
 (0)