Skip to Content
Logo of RG Logo of RG
  • Home
  • Shop
  • Events
  • Courses
  • Company
    • News
    • Success Stories
  • Odoo Docs 19
  • Appointment
  • Jobs
  • Contact us
  • 0
  • 0
  • +1 555-555-5556
  • Sign in
Logo of RG Logo of RG
  • 0
  • 0
    • Home
    • Shop
    • Events
    • Courses
    • Company
      • News
      • Success Stories
    • Odoo Docs 19
    • Appointment
    • Jobs
    • Contact us
  • +1 555-555-5556
  • Sign in
Odoo Docs 19
Home Components Guides Classes Search
418 components
Overlay
  • Accordion Item
  • Barcode Dialog
  • Bottom Sheet
  • Calendar Common Popover
  • Calendar Year Popover
  • Confirmation Dialog
  • Date Time Picker Popover
  • dialog
  • Domain Selector Dialog
  • Dropdown
  • Dropdown Group
  • Dropdown Item
  • Dropdown Popover
  • Error504 Dialog
  • Error Dialog
  • Export Data Dialog
  • Expression Editor Dialog
  • Form Error Dialog
  • Form View Dialog
  • Kanban Column Examples Dialog
  • Kanban Cover Image Dialog
  • Kanban Dropdown Menu Wrapper
  • List Confirmation Dialog
  • Model Field Selector Popover
  • Multi Create Popover
  • Multi Currency Popover
  • popover
  • Redirect Warning Dialog
  • Res User Group Ids Popover
  • Scss Error Display
  • Select Create
  • Select Create Dialog
  • Session Expired Dialog
  • Signature Dialog
  • Warning Dialog
  1. Components
  2. Form View Dialog
OWL overlay

Form View Dialog

Odoo 19 OWL component — Form View Dialog (views)

Live preview Interactive
Source excerpt web/static/src/views/view_dialogs/form_view_dialog.js
import { Dialog } from "@web/core/dialog/dialog";
import { useChildRef, useService } from "@web/core/utils/hooks";
import { CallbackRecorder } from "@web/search/action_hook";
import { View } from "@web/views/view";

import { Component } from "@odoo/owl";

export class FormViewDialog extends Component {
    static template = "web.FormViewDialog";
    static components = { Dialog, View };
    static props = {
        close: Function,
        resModel: String,

        context: { type: Object, optional: true },
        expandedFormRef: { type: String, optional: true },
        nextRecordsContext: { type: Object, optional: true },
        readonly: { type: Boolean, optional: true },
        onRecordSaved: { type: Function, optional: true },
        onRecordSave: { type: Function, optional: true },
        onRecordDiscarded: { type: Function, optional: true },
        removeRecord: { type: Function, optional: true },
        resId: { type: [Number, Boolean], optional: true },
        title: { type: String, optional: true },
        viewId: { type: [Number, Boolean], optional: true },
        preventCreate: { type: Boolean, optional: true },
        preventEdit: { type: Boolean, optional: true },
        canExpand: { type: Boolean, optional: true },
        isToMany: { type: Boolean, optional: true },
        size: Dialog.props.size,
    };
    static defaultProps = {
        onRecordSaved: () => {},
        preventCreate: false,
        preventEdit: false,
        canExpand: true,
        isToMany: false,
    };

    setup() {
        super.setup();

        this.actionService = useService("action");
        this.modalRef = useChildRef();
        this.env.dialogData.dismiss = () => this.discardRecord();

        const buttonTemplate = this.props.isToMany
            ? "web.FormViewDialog.ToMany.buttons"
            : "web.FormViewDialog.ToOne.buttons";

        this.currentResId = this.props.resId;

        if (this.props.canExpand) {
            this.onExpandCallback = this.onExpand.bind(this);
        }

        this.viewProps = {
            type: "form",
            buttonTemplate,

            context: this.props.context || {},
            display: { controlPanel: false },
            readonly: this.props.readonly,
            resId: this.props.resId || false,
            resModel: this.props.resModel,
            viewId: this.props.viewId || false,
            preventCreate: this.props.preventCreate,
            preventEdit: this.props.preventEdit,
            discardRecord: this.discardRecord.bind(this),
            saveRecord: async (record, params) => {
                let saved;
                if (this.props.onRecordSave) {
                    saved = await this.props.onRecordSave(record);
                } else {
                    saved = await record.save({ reload: false });
                    if (saved) {
                        this.currentResId = record.resId;
                        await this.props.onRecordSaved(record);
                    }
                }
                if (saved) {
                    await this.onRecordSaved(record, params);
                }
                return saved;
            },

            __beforeLeave__: new CallbackRecorder(),
        };
        if (this.props.removeRecord) {
            this.viewProps.removeRecord = async () => {
                await this.props.removeRecord();
                this.props.close();
            };
        }
    }

    /**
     * overridable method defining what to do on save
     * @param {*} record, record that was saved
     * @param {*} params, additional parameters passed to "save"
     */
    async onRecordSaved(record, params) {
        if (params?.saveAndNew) {
            this.currentResId = false;
            const context = this.props.nextRecordsContext || this.props.context || {};
            await record.model.load({ resId: false, context });
        } else {
            this.props.close();
        }
    }

    async discardRecord() {
        if (this.props.onRecordDiscarded) {
            await this.props.onRecordDiscarded();
        }
        this.props.close();
    }

    async onExpand() {
        const beforeLeaveCallbacks = this.viewProps.__beforeLeave__.callbacks;
Registry / API
Registry name
FormViewDialog
Category
—
Module
web
Slug
form-view-dialog
Nav group
overlay
Follow us

250 Executive Park Blvd, Suite 3400
San Francisco CA 94134

  • +1 555-555-5556
  • info@yourcompany.example.com
Copyright © Company name
Powered by Odoo - The #1 Open Source eCommerce