rules repository

A-0960 Try to give modal dialogs a Cancel button.

Severity Warning Check + SQL-based Test Free New

Reason

A modal dialog (this includes drawers) should offer an explicit way to leave without saving. Relying on the close icon in the dialog header is easy to miss and far away from the primary action. Add a button and a dynamic action on that button (event Click) with the true action Cancel Dialog or Close Dialog. The button name does not matter; the rule looks for the dynamic action.

If a dialog intentionally has no cancel path (for example a mandatory acknowledgement), switch the rule off for that page and document why.

Example

Non-Compliant Example

page 10 (
    // ...
    appearance {
        pageMode: modalDialog
        dialogTemplate: @/modal-dialog // or @/drawer
    }
    // no button with a Cancel Dialog / Close Dialog dynamic action
)
Issues
LineColumnMessage
419Modal dialog page has no button that closes or cancels the dialog.

Compliant Solution - ★★★★★

page 10 (
    // ...
    appearance {
        pageMode: modalDialog
        dialogTemplate: @/modal-dialog // or @/drawer
    }

    button cancel (
        buttonName: CANCEL
        label: Cancel
        behavior {
            type: standard
            action: definedByDynamicAction
        }
        // ...
    )

    dynamicAction cancel-dialog (
        name: Cancel Dialog
        // ...
        when {
            event: click
            selectionType: button
            button: @cancel
        }

        action native-dialog-cancel (
            action: cancelDialog // closeDialog is accepted as well
            // ...
        )
    )
)

Tests

Test SQL query

select aa.workspace || '.' || aa.alias || '.' || ap.page_id as identifier,
       'Modal dialog page ' || ap.page_id || ' of app ' || aa.alias || ' in ' || aa.workspace
         || ' has no button that closes or cancels the dialog.' as message
  from apex_application_pages ap
  join apex_applications aa
    on aa.application_id = ap.application_id
       and aa.workspace = ap.workspace
 where aa.workspace in (#ApexWorkspaces#)
   and ap.page_mode = 'Modal Dialog'
   and not exists (select 1
                     from apex_application_page_buttons pb
                     join apex_application_page_da da
                       on da.application_id = pb.application_id
                          and da.page_id = pb.page_id
                          and da.when_button_id = pb.button_id
                     join apex_application_page_da_acts act
                       on act.application_id = da.application_id
                          and act.dynamic_action_id = da.dynamic_action_id
                    where pb.application_id = ap.application_id
                      and pb.page_id = ap.page_id
                      and act.action_code in ('NATIVE_DIALOG_CANCEL', 'NATIVE_DIALOG_CLOSE'))

Test results

IdentifierMessageMigration
WORKSPACE.CUSTOMERS.10Modal dialog page 10 of app CUSTOMERS in WORKSPACE has no button that closes or cancels the dialog.-

Parameters

Use parameters to customize the rule to your needs.

ParameterDescriptionDefault Value
ApexWorkspacesComma-separated List of APEX workspaces owning APEX applications to check.dblinter, dbl_gui

References