Skip to content
17 changes: 17 additions & 0 deletions awesome_owl/static/src/card/card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useState, Component } from "@odoo/owl";

export class Card extends Component {
static template = "awesome_owl.card";
static props = {
title: String,
slots: { type: Object, optional: true },
};

setup() {
this.state = useState({ visible: true });
}

toggleVisible() {
this.state.visible = !this.state.visible;
}
}
16 changes: 16 additions & 0 deletions awesome_owl/static/src/card/card.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">

<t t-name="awesome_owl.card">
<div class="card d-inline-block m-2" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">
<t t-esc="props.title"/>
<span class="fa" t-att-class="{'fa-angle-down': state.visible, 'fa-angle-up': !state.visible}" t-on-click="toggleVisible"/>
</h5>
<t t-if="state.visible" t-slot="default"/>
</div>
</div>
</t>

</templates>
22 changes: 22 additions & 0 deletions awesome_owl/static/src/counter/counter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useState, Component } from "@odoo/owl";

export class Counter extends Component {
static template = "awesome_owl.counter";
static props = {
onChange: {
type: Function,
optional: true,
},
};

setup() {
this.state = useState({ value: 1 });
}

increment() {
this.state.value++;
if (this.props.onChange) {
this.props.onChange();
}
}
}
9 changes: 9 additions & 0 deletions awesome_owl/static/src/counter/counter.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">

<t t-name="awesome_owl.counter">
<p>Counter: <t t-esc="state.value"/></p>
<button type="button" class="btn btn-primary" t-on-click="increment">Increment</button>
</t>

</templates>
3 changes: 1 addition & 2 deletions awesome_owl/static/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import { Playground } from "./playground";

const config = {
dev: true,
name: "Owl Tutorial"
name: "Owl Tutorial",
};

// Mount the Playground component when the document.body is ready
whenReady(() => mountComponent(Playground, document.body, config));

17 changes: 16 additions & 1 deletion awesome_owl/static/src/playground.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
import { Component } from "@odoo/owl";
import { markup, useState, Component } from "@odoo/owl";
import { Counter } from "./counter/counter";
import { Card } from "./card/card";
import { TodoList } from "./todo/todo-list";

export class Playground extends Component {
static template = "awesome_owl.playground";
static components = { Counter, Card, TodoList };

setup() {
this.state = useState({ sum: 2 });
}

incrementSum() {
this.state.sum++;
}

someHtmlEscaped = "<div class='text-primary'>My content</div>";
someHtml = markup("<div class='text-primary'>My content</div>");
}
19 changes: 16 additions & 3 deletions awesome_owl/static/src/playground.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,22 @@
<templates xml:space="preserve">

<t t-name="awesome_owl.playground">
<div class="p-3">
hello world
</div>
<Card title="'Some text'">
<p><t t-esc="someHtmlEscaped"/></p>
<p><t t-out="someHtml"/></p>
</Card>
<Card title="'My first counter'">
<Counter onChange.bind="incrementSum"/>
</Card>
<Card title="'My second counter'">
<Counter onChange.bind="incrementSum"/>
</Card>
<Card title="'The sum of both counters'">
<p>The sum is <t t-esc="state.sum"/></p>
</Card>
<Card title="'My groceries'">
<TodoList/>
</Card>
</t>

</templates>
13 changes: 13 additions & 0 deletions awesome_owl/static/src/todo/todo-item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Component } from "@odoo/owl";

export class TodoItem extends Component {
static template = "awesome_owl.todo-item";
static props = {
todo: {
type: Object,
shape: { id: Number, description: String, isCompleted: Boolean },
},
toggleState: Function,
removeTodo: Function,
};
}
15 changes: 15 additions & 0 deletions awesome_owl/static/src/todo/todo-item.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">

<t t-name="awesome_owl.todo-item">
<div class="form-check">
<input class="form-check-input" type="checkbox" t-on-change="() => props.toggleState(props.todo.id)" t-att-id="props.todo.id" t-att-checked="props.todo.isCompleted"/>
<label t-att-for="props.todo.id" t-att-class="{'text-muted text-decoration-line-through': props.todo.isCompleted}">
<t t-esc="props.todo.id"/>
<t t-esc="props.todo.description"/>
</label>
<span role="button" class="fa fa-remove" t-on-click="() => props.removeTodo(props.todo.id)"/>
</div>
</t>

</templates>
42 changes: 42 additions & 0 deletions awesome_owl/static/src/todo/todo-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useState, Component } from "@odoo/owl";
import { TodoItem } from "./todo-item";
import { useAutoFocus } from "../utils";

export class TodoList extends Component {
static template = "awesome_owl.todo-list";
static components = { TodoItem };

setup() {
this.state = useState({ todos: [], nextId: 1 });
useAutoFocus("new-todo-input");
}

input_event_handler(event) {
// keyCode is deprecated, use key instead
if (event.key === "Enter") {
if (event.target.value) {
this.state.todos.push({
id: this.state.nextId,
description: event.target.value,
isCompleted: false,
});
this.state.nextId++;
event.target.value = "";
}
}
}

toggleState(todoId) {
const selectedTodo = this.state.todos.find((todo) => todo.id === todoId);
if (selectedTodo) {
selectedTodo.isCompleted = !selectedTodo.isCompleted;
}
}

removeTodo(todoId) {
const index = this.state.todos.findIndex((todo) => todo.id === todoId);
if (index >= 0) {
this.state.todos.splice(index, 1);
}
}
}
11 changes: 11 additions & 0 deletions awesome_owl/static/src/todo/todo-list.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">

<t t-name="awesome_owl.todo-list">
<input type="text" placeholder="Enter a new task" t-ref="new-todo-input" t-on-keyup="input_event_handler"/>
<t t-foreach="state.todos" t-as="item" t-key="item.id">
<TodoItem todo="item" toggleState.bind="toggleState" removeTodo.bind="removeTodo"/>
</t>
</t>

</templates>
9 changes: 9 additions & 0 deletions awesome_owl/static/src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useEffect, useRef } from "@odoo/owl";

export function useAutoFocus(name) {
const ref = useRef(name);
useEffect(
(el) => el && el.focus(),
() => [ref.el]
);
}