Компоненти Owl

Фреймворк Odoo Javascript використовує спеціальний фреймворк компонентів під назвою Owl. Це декларативна система компонентів, частково натхненна Vue та React. Компоненти визначаються за допомогою QWeb шаблонів, доповнених деякими специфічними для Owl директивами. Офіційна документація Owl містить повний довідник та підручник.

Важливо

Хоча код можна знайти в модулі web, він зберігається з окремого репозиторію GitHub. Тому будь-які зміни до Owl слід вносити через запит на зміну на https://github.com/odoo/owl.

Примітка

Наразі всі версії Odoo (починаючи з версії 14) використовують одну й ту саму версію Owl.

Використання компонентів Owl

У Owl документація вже детально описано фреймворк Owl, тому на цій сторінці буде надано лише інформацію, специфічну для Odoo. Але спочатку давайте подивимося, як можна створити простий компонент в Odoo.

const { useState } = owl.hooks;
const { xml } = owl.tags;

class MyComponent extends Component {
    setup() {
        this.state = useState({ value: 1 });
    }

    increment() {
        this.state.value++;
    }
}
MyComponent.template = xml
    `<div t-on-click="increment">
        <t t-esc="state.value">
    </div>`;

Цей приклад показує, що Owl доступний як бібліотека в глобальному просторі імен як owl: його можна просто використовувати, як і більшість бібліотек в Odoo. Зверніть увагу, що ми визначили тут шаблон як статичну властивість, але без використання ключового слова static, яке недоступне в деяких браузерах (код javascript Odoo повинен відповідати стандарту Ecmascript 2019).

Тут ми визначаємо шаблон у коді javascript за допомогою допоміжного засобу xml. Однак це корисно лише для початку роботи. На практиці шаблони в Odoo слід визначати в файлі xml, щоб їх можна було перекладати. У цьому випадку компонент повинен визначати лише назву шаблону.

На практиці більшість компонентів повинні визначати 2 або 3 файли, розташовані в одному місці: файл javascript (my_component.js), файл шаблону (my_component.xml) і, за бажанням, файл scss (або css) (my_component.scss). Ці файли потім слід додати до якогось пакету ресурсів. Веб-фреймворк подбає про завантаження файлів javascript/css та завантаження шаблонів в Owl.

Ось як слід визначити вищезгаданий компонент:

const { useState } = owl.hooks;

class MyComponent extends Component {
    ...
}
MyComponent.template = 'myaddon.MyComponent';

А шаблон тепер знаходиться у відповідному xml-файлі:

<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">

<t t-name="myaddon.MyComponent">
  <div t-on-click="increment">
    <t t-esc="state.value"/>
  </div>
</t>

</templates>

Примітка

Назви шаблонів повинні відповідати домовленості addon_name.ComponentName.

Перегляньте також

Кращі практики

Перш за все, компоненти є класами, тому вони мають конструктор. Але конструктори є спеціальними методами в javascript, які не можна перезаписати жодним чином. Оскільки це іноді корисний шаблон в Odoo, ми повинні переконатися, що жоден компонент в Odoo безпосередньо не використовує метод конструктора. Натомість компоненти повинні використовувати метод setup:

// correct:
class MyComponent extends Component {
    setup() {
        // initialize component here
    }
}

// incorrect. Do not do that!
class IncorrectComponent extends Component {
    constructor(parent, props) {
        // initialize component here
    }
}

Ще однією гарною практикою є використання узгодженої домовленості для назв шаблонів: addon_name.ComponentName. Це запобігає конфлікту назв між додатками odoo.

Список посилань

Веб-клієнт Odoo побудований на компонентах Owl. Для спрощення роботи фреймворк Odoo javascript надає набір загальних компонентів, які можна повторно використовувати в деяких типових ситуаціях, таких як випадаючі меню, прапорці або календарі. На цій сторінці пояснюється, як використовувати ці загальні компоненти.

Технічна назва

Короткий опис

ActionSwiper

компонент свайпера для виконання дій під час сенсорного свайпу

CheckBox

простий компонент-чекбокс з міткою поруч

ColorList

список кольорів на вибір

Dropdown

повнофункціональний випадаючий список

Notebook

компонент для навігації між сторінками за допомогою вкладок

Pager

невеликий компонент для обробки пагінації

SelectMenu

компонент, що випадає, для вибору між різними опціями

TagsList

список тегів, що відображаються у вигляді округлих таблеток

ActionSwiper

Розташування

@web/core/action_swiper/action_swiper

Опис

Це компонент, який може виконувати дії, коли елемент свайпом проводиться горизонтально. Свайпер обтікає цільовий елемент, додаючи до нього дії. Дія виконується, як тільки користувач відпустить свайпер, пройшовши частину його ширини.

<ActionSwiper onLeftSwipe="Object" onRightSwipe="Object">
  <SomeElement/>
</ActionSwiper>

Найпростіший спосіб використання компонента - це використання його навколо цільового елемента безпосередньо в шаблоні xml, як показано вище. Але іноді може знадобитися розширити існуючий елемент, не дублюючи шаблон. Це можна зробити.

Якщо ви хочете розширити поведінку існуючого елемента, ви повинні розмістити елемент всередині, обернувши його безпосередньо. Крім того, ви можете умовно додати властивості, щоб керувати тим, коли елемент може бути прокручуваним, його анімацією та мінімальною частиною, яку потрібно прокрутити, щоб виконати дію.

Ви можете використовувати компонент для легкої взаємодії із записами, повідомленнями, елементами у списках та багатьма іншими функціями.

Приклад використання ActionSwiper

У наступному прикладі створюється базовий компонент ActionSwiper. Тут свайп увімкнено в обох напрямках.

<ActionSwiper
  onRightSwipe="
    {
      action: '() => Delete item',
      icon: 'fa-delete',
      bgColor: 'bg-danger',
    }"
  onLeftSwipe="
    {
      action: '() => Star item',
      icon: 'fa-star',
      bgColor: 'bg-warning',
    }"
>
  <div>
    Swipable item
  </div>
</ActionSwiper>

Примітка

Дії переставляють місцями під час використання мов із письмом справа наліво (RTL).

Props

Name

Тип

Опис

animationOnMove

Boolean

необов’язкове логічне значення для визначення, чи присутній ефект переміщення під час проведення пальцем

animationType

String

додаткова анімація, яка використовується після завершення свайпу (bounce або forwards)

onLeftSwipe

Object

якщо є, свайпер дій можна провести ліворуч

onRightSwipe

Object

якщо є, свайпер дій можна провести праворуч

swipeDistanceRatio

Number

необов’язкове мінімальне співвідношення ширини, яке потрібно провести пальцем для виконання дії

Ви можете використовувати обидва пропи onLeftSwipe та onRightSwipe одночасно.

Object, що використовується для прокрутки вліво/вправо, повинен містити:

  • action – це викликувана Function, яка служить зворотним викликом. Після завершення свайпу в заданому напрямку виконується ця дія.

  • icon – це клас іконок, який слід використовувати, зазвичай для представлення дії. Він має бути рядком.

  • bgColor – це колір фону, що використовується для декорування дії. Може бути одним із наступних значень контекстного кольору bootstrap (danger, info, secondary, success або warning).

Ці значення необхідно задати для визначення поведінки та візуального аспекту свайпера.

Приклад: Розширення існуючих компонентів

У наступному прикладі ви можете використовувати xpath для обгортання існуючого елемента в компоненті ActionSwiper. Тут додано свайпер, щоб позначити повідомлення як прочитане в пошті.

<xpath expr="//*[hasclass('o_Message')]" position="after">
  <ActionSwiper
    onRightSwipe="messaging.device.isMobile and messageView.message.isNeedaction ?
      {
        action: () => messageView.message.markAsRead(),
        icon: 'fa-check-circle',
        bgColor: 'bg-success',
      } : undefined"
  />
</xpath>
<xpath expr="//ActionSwiper" position="inside">
  <xpath expr="//*[hasclass('o_Message')]" position="move"/>
</xpath>

CheckBox

Розташування

@web/core/checkbox/checkbox

Опис

Це простий компонент-прапорець із міткою поруч. Чекбокс пов’язаний із міткою: прапорець перемикається щоразу, коли натискається на мітку.

<CheckBox value="boolean" disabled="boolean" t-on-change="onValueChange">
  Some Text
</CheckBox>

Props

Name

Тип

Опис

value

boolean

якщо true, чекбокс встановлюється, інакше він знімається

disabled

boolean

якщо true, чекбокс вимкнений, інакше він увімкнений

ColorList

Розташування

@web/core/colorlist/colorlist

Опис

ColorList дозволяє вибрати колір із заздалегідь визначеного списку. За замовчуванням компонент відображає поточний вибраний колір і не розгортається, доки не з’являється props canToggle. Різні пропи можуть змінювати його поведінку, щоб список завжди розгортався або щоб він діяв як перемикач після натискання, відображаючи список доступних кольорів, доки не буде зроблено вибір.

Props

Name

Тип

Опис

canToggle

boolean

необов’язково. Чи може список кольорів розгортатися після клацання

colors

array

список кольорів для відображення в компоненті. Кожен колір має унікальний id

forceExpanded

boolean

необов’язково. Якщо значення true, список завжди розгортається

isExpanded

boolean

необов’язково. Якщо значення true, список розгортається за замовчуванням

onColorSelected

function

зворотний виклик виконується після вибору кольору

selectedColor

number

необов’язково. Вибраний колір id

id кольорів такі:

Id

Color

0

No color

1

Red

2

Orange

3

Yellow

4

Light blue

5

Dark purple

6

Salmon pink

7

Medium blue

8

Dark blue

9

Fuchsia

12

Green

11

Purple

Розташування

@web/core/dropdown/dropdown та @web/core/dropdown/dropdown_item

Опис

Випадаючі меню – це напрочуд складні компоненти. Вони повинні надавати багато функцій, таких як:

  • Перемикання списку елементів при кліці

  • Випадаючі меню прямих братів і сестер: коли одне відкрите, перемикати інші при наведенні курсора

  • Закривається зовнішнім кліком

  • За потреби закрити список елементів, коли елемент вибрано

  • Викликати функцію, коли елемент вибрано

  • Підтримка випадаючих підменю до будь-якого рівня

  • SIY: стилізуйте самі

  • Налаштовувана гаряча клавіша для відкриття/закриття випадаючого списку або вибору елемента випадаючого списку

  • Навігація за допомогою клавіатури (стрілки, Tab, Shift+Tab, Home, End, Enter та Escape)

  • Змінює положення щоразу, коли сторінка прокручується або змінюється її розмір

  • Розумно обрано напрямок відкриття (напрямок справа наліво обробляється автоматично).

Щоб вирішити ці проблеми раз і назавжди, фреймворк Odoo надає набір із двох компонентів: компонент Dropdown (власне випадаючий список) та DropdownItem для кожного елемента у списку елементів.

<Dropdown>
  <t t-set-slot="toggler">
    <!-- "toggler" slot content is rendered inside a button -->
    Click me to toggle the dropdown menu !
  </t>
  <!-- "default" slot content is rendered inside a div -->
  <DropdownItem onSelected="selectItem1">Menu Item 1</DropdownItem>
  <DropdownItem onSelected="selectItem2">Menu Item 2</DropdownItem>
</Dropdown>

Props

Компонент <Dropdown/> - це просто <div class="dropdown"/> з <button class="dropdown-toggle"/> поруч з div меню (<div class="dropdown-menu"/>). Кнопка відповідає за присутність меню в DOM чи ні.

Dropdown

Тип

Опис

startOpen

boolean

початковий стан відкритого випадаючого меню (за замовчуванням false)

menuClass

string

додатковий клас CSS, застосований до випадаючого меню <div class="dropdown-menu"/>

togglerClass

string

додатковий клас CSS, застосований до перемикача <button class="dropdown-toggle"/>

hotkey

string

гаряча клавіша для перемикання відкриття за допомогою клавіатури

tooltip

string

додати підказку до перемикача

beforeOpen

function

hook для виконання логіки безпосередньо перед відкриттям. Може бути асинхронним.

manualOnly

boolean

якщо значення true, перемикати/відображати випадаючий список лише при натисканні кнопки (за замовчуванням значення false)

disabled

boolean

вимкнути (якщо значення true) кнопку випадаючого списку (за замовчуванням значення false)

title

string

вміст атрибута title для <button class="dropdown-toggle"/> (за замовчуванням: немає)

position

string

визначає бажану позицію відкриття меню. Напрямок RTL застосовується автоматично. Повинна бути коректною позицією хука usePosition. (за замовчуванням: bottom-start)

toggler

"parent" або undefined

якщо встановлено значення "parent", <button class="dropdown-toggle"/> не відтворюється (тому слот toggler ігнорується), а функція перемикання обробляється батьківським вузлом (наприклад, варіант використання: pivot cells). (за замовчуванням: undefined)

<DropdownItem/> – це просто діапазон (<span class="dropdown-item"/>). Коли <DropdownItem/> вибрано, викликається його властивість onSelected. Якщо ця властивість є методом, переконайтеся, що вона пов’язана, якщо методу потрібно використовувати значення this.

DropdownItem

Тип

Опис

onSelected

Функція

функція, яка буде викликана при виборі елемента з випадаючого списку.

parentClosingMode

none | closest | all

коли елемент вибрано, керуйте тим, який батьківський випадаючий список буде закрито: жоден, найближчий або всі (за замовчуванням = all)

hotkey

string

додаткова гаряча клавіша для вибору елемента

href

string

якщо його надано, DropdownItem стане <a href="value" class="dropdown-item"/> замість <span class="dropdown-item"/>. (за замовчуванням: не надано)

title

string

необов’язковий атрибут title, який буде передано кореневому вузлу DropdownItem. (за замовчуванням: не надано)

dataset

Об’єкт

необов’язковий об’єкт, що містить значення, які слід додати до набору даних кореневого елемента. Це можна використовувати для того, щоб елемент було легше знаходити програмно, наприклад, у тестах або турах.

Технічні примітки

Відрендерений DOM структурований так:

<div class="dropdown">
    <button class="dropdown-toggle">Click me !</button>
    <!-- following <div/> will or won't appear in the DOM depending on the state controlled by the preceding button -->
    <div class="dropdown-menu">
        <span class="dropdown-item">Menu Item 1</span>
        <span class="dropdown-item">Menu Item 2</span>
    </div>
</div>

Щоб правильно використовувати компонент <Dropdown/>, вам потрібно заповнити два OWL слоти :

  • слот toggler: він містить елементи перемикач вашого випадаючого списку та відображається всередині кнопки випадаючого списку (якщо властивість toggler не встановлена на parent),

  • слот default: він містить елементи самого випадаючого меню та відображається всередині <div class="dropdown-menu"/>. Хоча це не є обов’язковим, зазвичай у слоті menu є принаймні один DropdownItem.

Коли кілька випадаючих списків мають один і той самий батьківський елемент у DOM, вони вважаються частиною групи та повідомлятимуть одне одного про зміни свого стану. Це означає, що коли один із цих випадаючих списків відкритий, інші автоматично відкриватимуться при наведенні курсора миші, без необхідності клацання.

Приклад: Випадаючий список прямих братів і сестер

Коли натискається один випадаючий перемикач (Файл, Редагувати або Про), інші відкриваються самостійно при наведенні курсора.

<div>
  <Dropdown>
    <t t-set-slot="toggler">File</t>
    <DropdownItem onSelected="() => this.onItemSelected('file-open')">Open</DropdownItem>
    <DropdownItem onSelected="() => this.onItemSelected('file-new-document')">New Document</DropdownItem>
    <DropdownItem onSelected="() => this.onItemSelected('file-new-spreadsheet')">New Spreadsheet</DropdownItem>
  </Dropdown>
  <Dropdown>
    <t t-set-slot="toggler">Edit</t>
    <DropdownItem onSelected="() => this.onItemSelected('edit-undo')">Undo</DropdownItem>
    <DropdownItem onSelected="() => this.onItemSelected('edit-redo')">Redo</DropdownItem>
    <DropdownItem onSelected="() => this.onItemSelected('edit-find')">Search</DropdownItem>
  </Dropdown>
  <Dropdown>
    <t t-set-slot="toggler">About</t>
    <DropdownItem onSelected="() => this.onItemSelected('about-help')">Help</DropdownItem>
    <DropdownItem onSelected="() => this.onItemSelected('about-update')">Check update</DropdownItem>
  </Dropdown>
</div>

Приклад: Багаторівневий випадаючий список (з t-call)

У цьому прикладі показано, як можна створити випадаюче меню File із підменю для піделементів New та Save as....

<t t-name="addon.Dropdown.File">
  <Dropdown>
    <t t-set-slot="toggler">File</t>
    <DropdownItem onSelected="() => this.onItemSelected('file-open')">Open</DropdownItem>
    <t t-call="addon.Dropdown.File.New"/>
    <DropdownItem onSelected="() => this.onItemSelected('file-save')">Save</DropdownItem>
    <t t-call="addon.Dropdown.File.Save.As"/>
  </Dropdown>
</t>

<t t-name="addon.Dropdown.File.New">
  <Dropdown>
    <t t-set-slot="toggler">New</t>
    <DropdownItem onSelected="() => this.onItemSelected('file-new-document')">Document</DropdownItem>
    <DropdownItem onSelected="() => this.onItemSelected('file-new-spreadsheet')">Spreadsheet</DropdownItem>
  </Dropdown>
</t>

<t t-name="addon.Dropdown.File.Save.As">
  <Dropdown>
    <t t-set-slot="toggler">Save as...</t>
    <DropdownItem onSelected="() => this.onItemSelected('file-save-as-csv')">CSV</DropdownItem>
    <DropdownItem onSelected="() => this.onItemSelected('file-save-as-pdf')">PDF</DropdownItem>
  </Dropdown>
</t>

Приклад: Багаторівневий випадаючий список (вкладений)

<Dropdown>
  <t t-set-slot="toggler">File</t>
  <DropdownItem onSelected="() => this.onItemSelected('file-open')">Open</DropdownItem>
  <Dropdown>
    <t t-set-slot="toggler">New</t>
    <DropdownItem onSelected="() => this.onItemSelected('file-new-document')">Document</DropdownItem>
    <DropdownItem onSelected="() => this.onItemSelected('file-new-spreadsheet')">Spreadsheet</DropdownItem>
  </Dropdown>
  <DropdownItem onSelected="() => this.onItemSelected('file-save')">Save</DropdownItem>
  <Dropdown>
    <t t-set-slot="toggler">Save as...</t>
    <DropdownItem onSelected="() => this.onItemSelected('file-save-as-csv')">CSV</DropdownItem>
    <DropdownItem onSelected="() => this.onItemSelected('file-save-as-pdf')">PDF</DropdownItem>
  </Dropdown>
</Dropdown>

Приклад: Рекурсивний багаторівневий випадаючий список

У цьому прикладі ми рекурсивно викликаємо шаблон для відображення деревоподібної структури.

<t t-name="addon.MainTemplate">
  <div>
    <t t-call="addon.RecursiveDropdown">
      <t t-set="name" t-value="'Main Menu'" />
      <t t-set="items" t-value="state.menuItems" />
    </t>
  </div>
</t>

<t t-name="addon.RecursiveDropdown">
  <Dropdown>
    <t t-set-slot="toggler"><t t-esc="name"/></t>
      <t t-foreach="items" t-as="item" t-key="item.id">

        <!-- If this item has no child: make it a <DropdownItem/> -->
        <t t-if="!item.childrenTree.length">
          <DropdownItem onSelected="() => this.onItemSelected(item)" t-esc="item.name"/>
        </t>
        <!-- Else: recursively call the current dropdown template. -->
        <t t-else="" t-call="addon.RecursiveDropdown">
          <t t-set="name" t-value="item.name" />
          <t t-set="items" t-value="item.childrenTree" />
        </t>

      </t>
    </t>
  </Dropdown>
</t>

Notebook

Розташування

@web/core/notebook/notebook

Опис

Блокнот створений для відображення кількох сторінок у інтерфейсі з вкладками. Вкладки можуть бути розташовані у верхній частині елемента для горизонтального відображення або ліворуч для вертикального розташування.

Існує два способи визначити сторінки Блокноту для створення екземплярів: або за допомогою slot, або передаючи спеціальний props.

Сторінку можна вимкнути за допомогою атрибута isDisabled, встановленого безпосередньо на вузлі слота, або в оголошенні сторінки, якщо Notebook використовується з pages, заданими як властивості. Після вимкнення відповідна вкладка стає сірою та також встановлюється як неактивна.

Props

Name

Тип

Опис

anchors

object

необов’язково. Дозволити навігацію за допомогою прив’язок до елементів усередині вкладок, які не видно.

className

string

необов’язково. Назва класу встановлено в кореневому каталозі компонента.

defaultPage

string

необов’язково. Сторінка id, яка відображатиметься за замовчуванням.

icons

array

необов’язково. Список піктограм, що використовуються на вкладках.

orientation

string

необов’язково. Напрямок табуляції - horizontal або vertical.

onPageUpdate

function

необов’язково. Зворотний виклик виконується після зміни сторінки.

pages

array

необов’язково. Містить список сторінок, які потрібно заповнити з шаблону.

Example

Перший підхід полягає у встановленні сторінок у слотах компонента.

<Notebook orientation="'vertical'">
  <t t-set-slot="page_1" title="'Page 1'" isVisible="true">
    <h1>My First Page</h1>
    <p>It's time to build Owl components. Did you read the documentation?</p>
  </t>
  <t t-set-slot="page_2" title="'2nd page'" isVisible="true">
    <p>Wise owl's silent flight. Through the moonlit forest deep, guides my path to code</p>
  </t>
</Notebook>

Інший спосіб визначення сторінок – це передача властивостей. Це може бути корисним, якщо деякі сторінки мають однакову структуру. Спочатку створіть компонент для кожного шаблону сторінки, який ви можете використовувати.

import { Notebook } from "@web/core/notebook/notebook";

class MyTemplateComponent extends owl.Component {
  static template = owl.tags.xml`
    <h1 t-esc="props.title" />
    <p t-esc="props.text" />
  `;
}

class MyComponent extends owl.Component {
  get pages() {
    return [
      {
        Component: MyTemplateComponent,
        title: "Page 1",
        props: {
          title: "My First Page",
          text: "This page is not visible",
        },
      },
      {
        Component: MyTemplateComponent,
        id: "page_2",
        title: "Page 2",
        props: {
          title: "My second page",
          text: "You're at the right place!",
        },
      },
    ]
  }
}
MyComponent.template = owl.tags.xml`
  <Notebook defaultPage="'page_2'" pages="pages" />
`;

Обидва приклади наведено тут:

Приклади з вертикальним та горизонтальним розташуванням

Пейджер

Розташування

@web/core/pager/pager

Опис

Пейджер – це невеликий компонент для обробки пагінації. Сторінка визначається параметрами offset та limit (розмір сторінки). Він відображає поточну сторінку та total кількість елементів, наприклад, «9-12 / 20». У попередньому прикладі offset дорівнює 8, limit – 4, а total – 20. Він має дві кнопки («Попередній» та «Наступний») для навігації між сторінками.

Примітка

Пейджер можна використовувати будь-де, але його основне застосування — на панелі керування. Дивіться хук usePager для керування пейджером панелі керування.

<Pager offset="0" limit="80" total="50" onUpdate="doSomething" />

Props

Name

Тип

Опис

offset

number

Індекс першого елемента сторінки. Він починається з 0, але пейджер відображає offset + 1.

limit

number

Розмір сторінки. Сума offset та limit відповідає індексу останнього елемента сторінки.

total

number

Загальна кількість елементів, яких може досягти сторінка.

onUpdate

function

Функція, яка викликається, коли сторінку змінює пейджер. Ця функція може бути асинхронною, пейджер не можна редагувати, поки вона виконується.

isEditable

boolean

Дозволяє клацнути на поточній сторінці для її редагування (за замовчуванням true).

withAccessKey

boolean

Прив’язує клавішу доступу p до кнопки попередньої сторінки та n до наступної сторінки (за замовчуванням true).

SelectMenu

Розташування

@web/core/select_menu/select_menu

Опис

Цей компонент можна використовувати, коли вам потрібно зробити більше, ніж просто використовувати вбудований елемент select. Ви можете визначити власний шаблон опцій, що дозволить пошук між вашими опціями, або згрупувати їх у підрозділи.

Примітка

Віддавайте перевагу нативному HTML-елементу select, оскільки він за замовчуванням забезпечує функції спеціальних можливостей та має кращий інтерфейс користувача на мобільних пристроях. Цей компонент розроблено для використання в складніших випадках використання, щоб подолати обмеження нативного елемента.

Props

Name

Тип

Опис

choices

array

необов’язково. Список choice вибору для відображення у випадаючому списку.

class

string

необов’язково. Назва класу встановлюється в кореневому елементі компонента SelectMenu.

groups

array

необов’язково. Список group, що містить choices для відображення у випадаючому списку.

multiSelect

boolean

необов’язково. Увімкнути множинний вибір. Коли множинний вибір увімкнено, вибрані значення відображаються як tag у вхідних даних SelectMenu.

togglerClass

string

необов’язково. назва класу встановлена на кнопці-перемикачі.

required

boolean

необов’язково. Чи можна скасувати вибір вибраного значення.

searchable

boolean

необов’язково. Чи відображається поле пошуку у випадаючому списку.

searchPlaceholder

string

необов’язково. Текст, що відображається як заповнювач поля пошуку.

value

any

необов’язково. Поточне вибране значення. Може бути будь-якого типу.

onSelect

function

необов’язково. Зворотний виклик виконується, коли вибрано опцію.

Форма choice така:

  • value – це фактичне значення вибору. Зазвичай це технічний рядок, але може бути будь-якого типу.

  • label – це текст, що відображається, пов’язаний з опцією. Зазвичай це більш зрозумілий та перекладений string.

Форма group така:

  • choices – це список choice, які потрібно відобразити для цієї групи.

  • label – це відображений текст, пов’язаний із групою. Це рядок, що відображається у верхній частині групи.

Example

У наступному прикладі SelectMenu відображатиме чотири варіанти. Один з них відображається поверх опцій, оскільки з ним не пов’язано жодних груп, але інші розділені міткою їхньої групи.

import { SelectMenu } from "@web/core/select_menu/select_menu";

class MyComponent extends owl.Component {
  get choices() {
    return [
        {
          value: "value_1",
          label: "First value"
        }
    ]
  }
  get groups() {
    return [
      {
          label: "Group A",
          choices: [
              {
                value: "value_2",
                label: "Second value"
              },
              {
                value: "value_3",
                label: "Third value"
              }
          ]
      },
      {
          label: "Group B",
          choices: [
              {
                value: "value_4",
                label: "Fourth value"
              }
          ]
      }
    ]
  }
}
MyComponent.template = owl.tags.xml`
  <SelectMenu
    choices="choices"
    groups="groups"
    value="'value_2'"
  />
`;

Ви також можете налаштувати зовнішній вигляд перемикача та встановити власний шаблон для варіантів вибору, використовуючи відповідні слоти компонентів.

MyComponent.template = owl.tags.xml`
  <SelectMenu
    choices="choices"
    groups="groups"
    value="'value_2'"
  >
    Make a choice!
    <t t-set-slot="choice" t-slot-scope="choice">
      <span class="coolClass" t-esc="'👉 ' + choice.data.label + ' 👈'" />
    </t>
  </SelectMenu>
`;
Приклад використання та налаштування SelectMenu

Коли SelectMenu використовується з множинним вибором, властивості value повинні бути масивом Array, що містить значення вибраних варіантів.

Приклад використання SelectMenu з множинним вибором

Для більш складних випадків використання ви можете налаштувати нижню частину випадаючого списку, використовуючи слот bottomArea. Тут ми вибираємо відображення кнопки з відповідним значенням, встановленим у полі пошуку.

MyComponent.template = owl.tags.xml`
  <SelectMenu
      choices="choices"
  >
      <span class="select_menu_test">Select something</span>
      <t t-set-slot="bottomArea" t-slot-scope="select">
          <div t-if="select.data.searchValue">
              <button class="btn text-primary" t-on-click="() => this.onCreate(select.data.searchValue)">
                  Create this article "<i t-esc="select.data.searchValue" />"
              </button>
          </div>
      </t>
  </SelectMenu>
`;
Приклад налаштування нижньої області SelectMenu

TagsList

Розташування

@web/core/tags_list/tags_list

Опис

Цей компонент може відображати список тегів у вигляді округлених таблиць. Ці теги можуть або просто перераховувати кілька значень, або бути редагованими, що дозволяє видаляти елементи. Можна обмежити кількість відображаних елементів за допомогою властивостей itemsVisible. Якщо список перевищує це обмеження, кількість додаткових елементів відображається в колі поруч з останнім тегом.

Props

Name

Тип

Опис

displayBadge

boolean

необов’язково. Чи відображається тег як значок.

displayText

boolean

необов’язково. Чи відображається тег із текстом чи ні.

itemsVisible

number

необов’язково. Обмеження видимих тегів у списку.

tags

array

список елементів tag, наданих компоненту.

Форма tag така:

  • colorIndex – це необов’язковий ідентифікатор кольору.

  • icon - це необов’язкова піктограма, що відображається безпосередньо перед відображеним текстом.

  • id – це унікальний ідентифікатор тегу.

  • img - це необов’язкове зображення, яке відображається в колі, безпосередньо перед відображеним текстом.

  • onClick - це необов’язковий зворотний виклик, який можна надати елементу. Це дозволяє батьківському елементу обробляти будь-яку функціональність залежно від тегу, на який було натиснуто.

  • onDelete - це необов’язковий зворотний виклик, який можна передати елементу. Це робить можливим видалення елемента зі списку тегів і має оброблятися батьківським елементом.

  • text – це відображений string, пов’язаний з тегом.

Example

У наступному прикладі компонент TagsList використовується для відображення кількох тегів. Розробник повинен з батьківського компонента керувати тим, що станеться при натисканні тегу або кнопки видалення.

import { TagsList } from "@web/core/tags_list/tags_list";

class Parent extends Component {
  setup() {
    this.tags = [{
        id: "tag1",
        text: "Earth"
    }, {
        colorIndex: 1,
        id: "tag2",
        text: "Wind",
        onDelete: () => {...}
    }, {
        colorIndex: 2,
        id: "tag3",
        text: "Fire",
        onClick: () => {...},
        onDelete: () => {...}
    }];
  }
}
Parent.components = { TagsList };
Parent.template = xml`<TagsList tags="tags" />`;

Залежно від атрибутів, наданих кожному тегу, їхній зовнішній вигляд та поведінка будуть відрізнятися.

Приклади використання різних властивостей та атрибутів у TagsList