Modals 

Actions that require a user's attention must be visualized by modal windows.

TYPO3 provides an API as basis to create modal windows with severity representation. For better UX, if actions (buttons) are attached to the modal, one button must be a positive action. This button should get a btnClass to highlight it.

Modals should be used rarely and only for confirmations. For information that does not require a confirmation the Notification API (flash message) should be used.

For complex content, like forms or a lot of information, use normal pages.

API 

The API provides only two public methods:

  1. TYPO3.Modal.confirm(title, content, severity, buttons)
  2. TYPO3.Modal.dismiss()

Modal settings 

Name Type
string
string|jQuery
int
object[]
bool
title
Type
string
Required
true

The title displayed in the modal

content
Type
string|jQuery
Required
true

The content displayed in the modal

severity
Type
int
Default
TYPO3.Severity.info

Represents the severity of a modal. Please see TYPO3.Severity .

buttons
Type
object[]

Actions rendered into the modal footer. If empty, the footer is not rendered. See section Modals on how to configure the buttons.

staticBackdrop
Type
bool
Default
false

Controls whether a static backdrop should be rendered, which prevents closing the modal by clicking outside of it.

Button settings 

Name Type
string
function
bool
string
text
Type
string
Required
true

The text rendered into the button.

trigger / action
Type
function
Required
true

Callback that is triggered on button click - either a simple function or DeferredAction / ImmediateAction

active
Type
bool

Marks the button as active. If true, the button gets the focus.

btnClass
Type
string

The CSS class for the button.

Data attributes 

It is also possible to use data attributes to trigger a modal, for example on an anchor element, which prevents the default behavior.

data-title
The title text for the modal.
data-content
The content text for the modal.
data-severity
The severity for the modal, default is info (see TYPO3.Severity.* ).
data-href
The target URL, default is the href attribute of the element.
data-button-close-text
Button text for the close/cancel button.
data-button-ok-text
Button text for the ok button.
class="t3js-modal-trigger"
Marks the element as modal trigger.
data-static-backdrop
Render a static backdrop to avoid closing the modal when clicking it.

Example:

EXT:my_extension/Resources/Private/Templates/SomeTemplate.fluid.html
<a
  href="delete.php"
  class="t3js-modal-trigger"
  data-title="Delete"
  data-content="Really delete?"
>
  delete
</a>
Copied!

Reacting to events of backend modals 

A modal dispatches the following events. Add event listeners to the modal that is returned by the API:

typo3-modal-show
Before the modal is opened.
typo3-modal-shown
After the modal has been opened.
typo3-modal-hide
Before the modal is closed.
typo3-modal-hidden
After the modal has been closed.
EXT:my_extension/Resources/Public/JavaScript/delete-conference.js
import Modal from '@typo3/backend/modal.js';

const modal = Modal.confirm(
  'Delete the conference?',
  'The talks of the conference are deleted as well.',
);

modal.addEventListener('typo3-modal-hidden', () => {
  // Runs after the modal has been closed, no matter how
  document.querySelector('#delete-conference')?.focus();
});
Copied!

Changed in version 14.0

Examples 

A basic modal (without anything special) can be created this way:

TYPO3.Modal.confirm('The title of the modal', 'This the the body of the modal');
Copied!

A modal as warning with button:

EXT:my_extension/Resources/Public/JavaScript/MyScript.js
TYPO3.Modal.confirm('Warning', 'You may break the internet!', TYPO3.Severity.warning, [
  {
    text: 'Break it',
    active: true,
    trigger: function() {
      // break the net
    }
  }, {
    text: 'Abort!',
    trigger: function() {
      TYPO3.Modal.dismiss();
    }
  }
]);
Copied!

A modal as warning:

TYPO3.Modal.confirm('Warning', 'You may break the internet!', TYPO3.Severity.warning);
Copied!

Action buttons in modals created by the TYPO3/CMS/Backend/Modal module may make use of TYPO3/CMS/Backend/ActionButton/ImmediateAction and TYPO3/CMS/Backend/ActionButton/DeferredAction .

As an alternative to the existing trigger option, the option action may be used with an instance of the previously mentioned modules.

EXT:my_extension/Resources/Public/JavaScript/MyScript.js
Modal.confirm('Header', 'Some content', Severity.error, [
  {
    text: 'Based on trigger()',
    trigger: function () {
      console.log('Vintage!');
    }
  },
  {
    text: 'Based on action',
    action: new DeferredAction(() => {
      return new AjaxRequest('/any/endpoint').post({});
    })
  }
]);
Copied!

Activating any action disables all buttons in the modal. Once the action is done, the modal disappears automatically.

Buttons of the type DeferredAction render a spinner on activation into the button.

A modal with static backdrop:

EXT:my_extension/Resources/Public/JavaScript/MyScript.js
import Modal from '@typo3/backend/modal.js';

Modal.advanced({
  title: 'Hello',
  content: 'This modal is not closable via clicking the backdrop.',
  size: Modal.sizes.small,
  staticBackdrop: true
});
Copied!

Templates, using the HTML class .t3js-modal-trigger to initialize a modal dialog are also able to use the new option by adding the data-static-backdrop attribute to the corresponding element.

EXT:my_extension/Resources/Private/Templates/SomeTemplate.fluid.html
<button class="btn btn-default t3js-modal-trigger"
  data-title="Hello"
  data-content="This modal is not closable via clicking the backdrop."
  data-static-backdrop>
  Open modal
</button>
Copied!

Rendering HTML content in a modal 

Plain string content, as used in the examples above, is HTML-escaped before being rendered.

To render real HTML, pass a lit html template result as content instead of a string:

EXT:my_extension/Resources/Public/JavaScript/MyScript.js
import Modal from '@typo3/backend/modal.js';
import { html } from 'lit';

button.addEventListener('click', (event) => {
  event.preventDefault();

  Modal.advanced({
    title: 'A header',
    content: html`<p>This is <strong>bold</strong> HTML content.</p>`,
    size: Modal.sizes.large,
  });
});
Copied!

Translated labels can be included the same way, using the lll() helper from @typo3/core/lit-helper.js. The label itself must first be made available to JavaScript via PageRenderer->addInlineLanguageLabel() :

EXT:my_extension/Classes/Controller/MyController.php (excerpt)
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use TYPO3\CMS\Core\Page\PageRenderer;

final class SomeController
{
  public function __construct(
    private readonly PageRenderer $pageRenderer,
  ) {}

  public function someAction(): void
  {
    $this->pageRenderer->loadJavaScriptModule('@my-vendor/my-extension/html-content-modal.js');
    $this->pageRenderer->addInlineLanguageLabel(
      'myExtension.modal.greeting',
      'Hello, %s!',
    );
  }
}
Copied!
EXT:my_extension/Resources/Public/JavaScript/MyScript.js
import Modal from '@typo3/backend/modal.js';
import { html } from 'lit';
import { lll } from '@typo3/core/lit-helper.js';

button.addEventListener('click', (event) => {
  event.preventDefault();

  Modal.advanced({
    title: 'A header',
    content: html`<p>${lll('myExtension.modal.greeting', 'World')}</p>`,
    size: Modal.sizes.large,
  });
});
Copied!