Налаштування типу представлення

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

Припустимо, нам потрібно створити власну версію загального представлення. Наприклад, представлення канбан з додатковим стрічкоподібним віджетом зверху (для відображення певної користувацької інформації). У такому випадку це можна зробити за кілька кроків:

  1. Розширте controller/renderer/model канбану та зареєструйте його в реєстрі переглядів.

    custom_kanban_controller.js
    /** @odoo-module */
    
    import { KanbanController } from "@web/views/kanban/kanban_controller";
    import { kanbanView } from "@web/views/kanban/kanban_view";
    import { registry } from "@web/core/registry";
    
    // the controller usually contains the Layout and the renderer.
    class CustomKanbanController extends KanbanController {
        // Your logic here, override or insert new methods...
        // if you override setup(), don't forget to call super.setup()
    }
    
    CustomKanbanController.template = "my_module.CustomKanbanView";
    
    export const customKanbanView = {
        ...kanbanView, // contains the default Renderer/Controller/Model
        Controller: CustomKanbanController,
    };
    
    // Register it to the views registry
    registry.category("views").add("custom_kanban", customKanbanView);
    

    У нашому користувацькому канбані ми визначили новий шаблон. Ми можемо або успадкувати шаблон контролера канбану та додати наші частини шаблону, або ж визначити абсолютно новий шаблон.

    custom_kanban_controller.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <templates>
        <t t-name="my_module.CustomKanbanView" t-inherit="web.KanbanView">
            <xpath expr="//Layout" position="before">
                <div>
                    Hello world !
                </div>
            </xpath>
        </t>
    </templates>
    
  2. Використовуйте представлення з атрибутом js_class в arch.

    <kanban js_class="custom_kanban">
        <templates>
            <t t-name="kanban-box">
                <!--Your comment-->
            </t>
        </templates>
    </kanban>
    

Можливості розширення представлень безмежні. Хоча ми тут розширили лише контролер, ви також можете розширити рендерер, щоб додавати нові кнопки, змінювати спосіб представлення записів або налаштовувати випадаючий список, а також розширювати інші компоненти, такі як модель та buttonTemplate.

Створення нового представлення з нуля

Створення нового подання – це складна тема. У цьому посібнику висвітлено лише основні кроки.

  1. Створіть controller.

    Основна роль контролера полягає в сприянні координації між різними компонентами представлення, такими як Renderer, Model та Layout.

    beautiful_controller.js
    /** @odoo-module */
    
    import { Layout } from "@web/search/layout";
    import { useService } from "@web/core/utils/hooks";
    import { Component, onWillStart, useState} from "@odoo/owl";
    
    export class BeautifulController extends Component {
        setup() {
            this.orm = useService("orm");
    
            // The controller create the model and make it reactive so whenever this.model is
            // accessed and edited then it'll cause a rerendering
            this.model = useState(
                new this.props.Model(
                    this.orm,
                    this.props.resModel,
                    this.props.fields,
                    this.props.archInfo,
                    this.props.domain
                )
            );
    
            onWillStart(async () => {
                await this.model.load();
            });
        }
    }
    
    BeautifulController.template = "my_module.View";
    BeautifulController.components = { Layout };
    

    Шаблон контролера відображає панель керування з Layout, а також renderer.

    beautiful_controller.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <templates xml:space="preserve">
        <t t-name="my_module.View">
            <Layout display="props.display" className="'h-100 overflow-auto'">
                <t t-component="props.Renderer" records="model.records" propsYouWant="'Hello world'"/>
            </Layout>
        </t>
    </templates>
    
  2. Створіть renderer.

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

    beautiful_renderer.js
    import { Component } from "@odoo/owl";
    export class BeautifulRenderer extends Component {}
    
    BeautifulRenderer.template = "my_module.Renderer";
    
    beautiful_renderer.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <templates xml:space="preserve">
        <t t-name="my_module.Renderer">
            <t t-esc="props.propsYouWant"/>
            <t t-foreach="props.records" t-as="record" t-key="record.id">
                // Show records
            </t>
        </t>
    </templates>
    
  3. Створіть модель.

    Роль моделі полягає в отриманні та управлінні всіма необхідними даними у поданні.

    beautiful_model.js
    /** @odoo-module */
    
    import { KeepLast } from "@web/core/utils/concurrency";
    
    export class BeautifulModel {
        constructor(orm, resModel, fields, archInfo, domain) {
            this.orm = orm;
            this.resModel = resModel;
            // We can access arch information parsed by the beautiful arch parser
            const { fieldFromTheArch } = archInfo;
            this.fieldFromTheArch = fieldFromTheArch;
            this.fields = fields;
            this.domain = domain;
            this.keepLast = new KeepLast();
        }
    
        async load() {
            // The keeplast protect against concurrency call
            const { length, records } = await this.keepLast.add(
                this.orm.webSearchRead(this.resModel, this.domain, [this.fieldsFromTheArch], {})
            );
            this.records = records;
            this.recordsLength = length;
        }
    }
    

    Примітка

    Для складних випадків, замість створення моделі з нуля, також можна використовувати RelationalModel, яка використовується іншими представленнями.

  4. Створіть arch парсер.

    Роль arch парсера полягає в розборі arch представлення, щоб воно мало доступ до інформації.

    beautiful_arch_parser.js
    /** @odoo-module */
    
    import { XMLParser } from "@web/core/utils/xml";
    
    export class BeautifulArchParser extends XMLParser {
        parse(arch) {
            const xmlDoc = this.parseXML(arch);
            const fieldFromTheArch = xmlDoc.getAttribute("fieldFromTheArch");
            return {
                fieldFromTheArch,
            };
        }
    }
    
  5. Створіть представлення та об’єднайте всі частини разом, а потім зареєструйте вигляд у реєстрі представлень.

    beautiful_view.js
    /** @odoo-module */
    
    import { registry } from "@web/core/registry";
    import { BeautifulController } from "./beautiful_controller";
    import { BeautifulArchParser } from "./beautiful_arch_parser";
    import { BeautifylModel } from "./beautiful_model";
    import { BeautifulRenderer } from "./beautiful_renderer";
    
    export const beautifulView = {
        type: "beautiful",
        display_name: "Beautiful",
        icon: "fa fa-picture-o", // the icon that will be displayed in the Layout panel
        multiRecord: true,
        Controller: BeautifulController,
        ArchParser: BeautifulArchParser,
        Model: BeautifulModel,
        Renderer: BeautifulRenderer,
    
        props(genericProps, view) {
            const { ArchParser } = view;
            const { arch } = genericProps;
            const archInfo = new ArchParser().parse(arch);
    
            return {
                ...genericProps,
                Model: view.Model,
                Renderer: view.Renderer,
                archInfo,
            };
        },
    };
    
    registry.category("views").add("beautifulView", beautifulView);
    
  6. Оголосіть представлення у файлі arch.

    ...
    <record id="my_beautiful_view" model="ir.ui.view">
      <field name="name">my_view</field>
      <field name="model">my_model</field>
      <field name="arch" type="xml">
          <beautiful fieldFromTheArch="res.partner"/>
      </field>
    </record>
    ...