Tùy chỉnh kiểu xem

Phân lớp một chế độ xem hiện có

Giả sử chúng ta cần tạo một phiên bản tùy chỉnh của chế độ xem chung. Ví dụ: chế độ xem kanban có thêm một số tiện ích giống dải băng ở trên cùng (để hiển thị một số thông tin tùy chỉnh cụ thể). Trong trường hợp đó, điều này có thể được thực hiện trong một vài bước:

  1. Mở rộng bộ điều khiển/trình kết xuất/mô hình Kanban và đăng ký nó trong sổ đăng ký chế độ xem.

    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);
    

    Trong Kanban tùy chỉnh của chúng tôi, chúng tôi đã xác định một mẫu mới. Chúng ta có thể kế thừa mẫu bộ điều khiển Kanban và thêm các phần mẫu của mình hoặc có thể xác định một mẫu hoàn toàn mới.

    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. Sử dụng chế độ xem với thuộc tính js_class trong Arch.

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

Khả năng mở rộng lượt xem là vô tận. Mặc dù chúng tôi chỉ mở rộng bộ điều khiển ở đây nhưng bạn cũng có thể mở rộng trình kết xuất để thêm các nút mới, sửa đổi cách trình bày bản ghi hoặc tùy chỉnh menu thả xuống cũng như mở rộng các thành phần khác như mô hình và buttonTemplate.

Tạo chế độ xem mới từ đầu

Tạo chế độ xem mới là một chủ đề nâng cao. Hướng dẫn này chỉ nêu bật các bước thiết yếu.

  1. Tạo bộ điều khiển.

    Vai trò chính của bộ điều khiển là tạo điều kiện thuận lợi cho việc phối hợp giữa các thành phần khác nhau của chế độ xem, chẳng hạn như Trình kết xuất, Mô hình và Bố cục.

    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 };
    

    Mẫu của Bộ điều khiển hiển thị bảng điều khiển với Bố cục và cả trình kết xuất.

    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. Tạo trình kết xuất.

    Chức năng chính của trình kết xuất là tạo ra biểu diễn dữ liệu trực quan bằng cách hiển thị chế độ xem bao gồm các bản ghi.

    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. Tạo mô hình.

    Vai trò của mô hình là truy xuất và quản lý tất cả dữ liệu cần thiết trong khung nhìn.

    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;
        }
    }
    

    Ghi chú

    Đối với các trường hợp nâng cao, thay vì tạo mô hình từ đầu, bạn cũng có thể sử dụng RelationalModel, được các chế độ xem khác sử dụng.

  4. Tạo trình phân tích cú pháp vòm.

    Vai trò của trình phân tích cú pháp vòm là phân tích chế độ xem vòm để chế độ xem có quyền truy cập vào thông tin.

    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. Tạo chế độ xem và kết hợp tất cả các phần lại với nhau, sau đó đăng ký chế độ xem trong sổ đăng ký chế độ xem.

    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. Khai báo view trong vòm.

    ...
    <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>
    ...