Интеграция Owl в odoo
Odoo определяет необходимые инструменты для переходного этапа, на котором будут сосуществовать легаси виджеты Odoo и компоненты Owl. Есть два возможных сценария:
- Компонент Owl должен создавать экземпляры легаси виджетов
- Легаси виджет должен создавать экземпляры компонентов Owl
Сценарий 1. Компонент Owl должен создавать экземпляры легаси виджетов
ComponentAdapter
это компонент Owl, предназначенный для использования в качестве универсального
адаптера для компонентов Owl, которые встраивают устаревшие виджеты Odoo (или динамически
как компоненты Owl, так и легаси виджеты Odoo), например::
Owl Component
|
ComponentAdapter (Owl компонент)
|
Legacy Widget(ы) (или Owl компоненты)
Адаптер принимает класс component/widget в качестве пропса Component
и
аргументы (кроме первого аргумента parent
) для инициализации его в качестве пропса.
Например:
<ComponentAdapter Component="LegacyWidget" params="params"/>
Буде транслирован в следующее:
const LegacyWidget = this.props.Component;
const legacyWidget = new LegacyWidget(this, this.props.params);
Если для инициализации устаревшего виджета задано более одного аргумента (в дополнение к parent
), то порядок аргументов (для инициализации суб виджета) должен быть определен. Есть две альтернативы. Можно либо (1) указать пропс widgetArgs
, соответствующий массиву аргументов, в противном случае (2) должен быть определен субкласс ComponentAdapter
. Этот
субкласс должен переопределять средство получения widgetArgs
для преобразования аргументов, полученных в качестве пропсов, в массив аргументов для вызова init
.
Например :
(1)
<ComponentAdapter Component="LegacyWidget" firstArg="a" secondArg="b" widgetsArgs="[a, b]"/>
(2)
class SpecificAdapter extends ComponentAdapter {
get widgetArgs() {
return [this.props.firstArg, this.props.secondArg];
}
}
<SpecificAdapter Component="LegacyWidget" firstArg="a" secondArg="b"/>
Если легаси виджет должен обновляться при изменении пропса, необходимо определить субкласс ComponentAdapter
, чтобы переопределить updateWidget
и renderWidget
. Функция updateWidget
принимает nextProps
в качестве аргумента и должна обновлять внутреннее состояние виджета (функция может быть асинхронной и возвращать объект Promise
). Однако, чтобы гарантировать, то что DOM обновляется сразу, он не должен выполнять ре-рендеринг. Эту роль берет на себя функция renderWidget
, которая будет вызвана непосредственно перед исправлением DOM и которая, таким образом, должна быть синхронной.
Например:
class SpecificAdapter extends ComponentAdapter {
updateWidget(nextProps) {
return this.widget.updateState(nextProps);
}
renderWidget() {
return this.widget.render();
}
}
Сценарий 2. Легаси виджет должен создавать экземпляры компонентов Owl
WidgetAdapterMixin
и ComponentWrapper
предназначены для
совместного использования, когда легаси виджету Odoo необходимо создать экземпляр компонентов Owl.
В этом случае иерархия виджетов/компонентов будет выглядеть следующим образом:
Легаси Виджет + WidgetAdapterMixin
|
ComponentWrapper (Owl компонент)
|
Owl компонент
В этом случае родительский легаси виджет должен использовать WidgetAdapterMixin
,
который гарантирует, то что хуки Owl (mounted
, willUnmount
, destroy
...)
правильно вызываются для субкомпонент. Более того, он должен создавать экземпляр
ComponentWrapper
и предоставьте ему класс компонентов Owl для использования вместе
с его пропсами. Этот враппер гарантирует, что компонент Owl будет
корректно обновлен (с помощью willUpdateProps
), как это было бы, если бы он был встроен
в иерархию Owl. Более того, этот враппер автоматически перенаправляет все
события, инициируемые компонентом Owl (или его потомками), на легаси
пользовательские события (trigger_up
) на родительском легаси виджете.
Пример:
class MyComponent extends Component {}
MyComponent.template = xml`<div>Owl компонент со значением <t t-esc="props.value"/></div>`;
const MyWidget = Widget.extend(WidgetAdapterMixin, {
start() {
this.component = new ComponentWrapper(this, MyComponent, {value: 44});
return this.component.mount(this.el);
},
update() {
return this.component.update({value: 45});
},
});