Skip to content

Modal view (dialog)

Example of a modal dialog with a form.

Modal view: client/custom/src/views/modals/my-dialog.js

define('custom:views/modals/my-dialog', ['views/modal', 'model'], (ModalView, Model) => {

    return class extends ModalView {

        className = 'dialog dialog-record'

        // language=Handlebars
        templateContent = `
            <div class="record no-side-margin">{{{record}}}</div>
        `,

        // If true, clicking on the backdrop will close the dialog.
        // Can be 'static', true or false.
        backdrop = true 

        setup() {
            // action buttons
            this.buttonList = [
                {
                    name: 'doSomething', // handler for 'doSomething' action is bellow
                    text: this.translate('Some Action', 'labels', 'MyScope'), // button label 
                    style: 'danger',
                    onClick: () => this.actionDoSomething(),
                },
                {
                    name: 'cancel',
                    label: 'Cancel',
                },
            ];

            const title = this.options.title || ''; // assuming it's passed from our parent view

            this.headerText = title;             
            // this.headerHtml = this.getHelper().escapeString(title);

            this.formModel = new Model();

            // define fields
            this.formModel.setDefs({
                fields: {
                    'someString': {
                        type: 'varchar', // field type
                        view: 'views/fields/varchar', // optional, to define custom view
                        required: true, // field param
                    },
                    'someCheckbox': {
                        type: 'bool',
                    },
                }
            });

            this.createView('record', 'views/record/edit-for-modal', {
                model: this.formModel,
                selector: '.record',                
                detailLayout: [ // form layout
                    {
                        rows: [
                            [
                                {
                                    name: 'someString',
                                    labelText: this.translate('someString', 'fields', 'MyScope'),
                                },
                                {
                                    name: 'someCheckbox',
                                    labelText: this.translate('Some Checkbox', 'labels', 'MyScope'),
                                },
                            ],
                        ],
                    },
                ],
            });
        }

        async actionDoSomething() {
            /** @type {import('views/record/edit').default} */
            const recordView = this.getView('record');

            const isValid = recordView.processFetch();

            if (!isValid) { 
                return;
            }

            Espo.Ui.notify(' ... ');

            const response = await Espo.Ajax.postRequest('MyScope/action/doSomething', {
                id: this.options.id, // passed from the parent view
                someString: this.formModel.attributes.someString,
                someCheckbox: this.formModel.attributes.someCheckbox,
            });

            Espo.Ui.success(this.translate('Done'));

            // We assume that the event 'done' will be caught by the parent view.
            this.trigger('done', response);

            // Close the modal dialog.
            this.close();
        }
    }
});

Parent view calling our modal view:

this.createView('dialog', 'custom:views/modals/my-dialog', {
    id: this.model.id,
    title: this.model.get('name'),                
}, view => {
    view.render();

    this.listenToOnce(view, 'done', response => {
        console.log(response);
    })
});

Simple dialog w/o separate view

this.createView('dialog', 'views/modal', {
    templateContent: '<p>{{complexText viewObject.options.message}}</p>',
    headerText: 'Hello world',
    backdrop: true,
    message: 'Some *message*\n\nHello world!',
    buttonList: [
        {
            name: 'doSomething',
            label: this.translate('Do Something'),
            onClick: () => {
                // Do something.
                this.close();
            },
            style: 'primary',
        },
        {
            name: 'close',
            label: this.translate('Close'),
        }
    ],
}, view => {
    view.render();
});