Deprecation: #91814 - Deprecate AbstractControl::setOnClick

See Issue #91814

Description

In favor of allowing Content-Security-Policy HTTP headers, inline JavaScript invocation via \TYPO3\CMS\Backend\Template\Components\AbstractControl::setOnClick has been deprecated. Existing instructions can be migrated using existing JavaScript helpers GlobalEventHandler or ActionDispatcher and their capabilities to provide similar functionality using data- attributes.

There might be scenarios that require a custom JavaScript module handling specific use cases that are not covered by mentioned JavaScript helpers.

Impact

Using affected PHP methods (see section below) will trigger PHP deprecation errors.

Affected Installations

All sites using 3rd party extensions that are using following methods directly or in inherited class implementations:

  • \TYPO3\CMS\Backend\Template\Components\AbstractControl->setOnClick
  • \TYPO3\CMS\Backend\Template\Components\AbstractControl->getOnClick

Migration

Mentioned JavaScript helpers cover most common use cases by using data- attributes instead of onclick event attributes with corresponding HTML elements.

  • consider replacing simple <a ... onclick="window.location.href=[URI]" with plain HTML links like <a href="[URI]">
  • replacing BackendUtility::viewOnClick, see documentation & examples
  • using data- attributes for GlobalEventHandler and ActionDispatcher, see documentation & examples

Example #1: open a new window/tab

$button->setOnClick(
    'window.open(\'' . $this->getDceEditLink($contentUid) . '\', \'editDcePopup\', ' .
    '\'height=768,width=1024,status=0,menubar=0,scrollbars=1\')'
);

Code block above being substituted with ActionDispatcher capabilities, using :html`data-dispatch-action` and data-dispatch-args HTML attributes:

$button->setDataAttributes([
    'dispatch-action' => 'TYPO3.WindowManager.localOpen',
    // JSON encoded representation of JavaScript function arguments
    // (HTML attributes are encoded in \TYPO3\CMS\Backend\Template\Components\Buttons\LinkButton)
    'dispatch-args' => GeneralUtility::jsonEncodeForHtmlAttribute([
        $this->getDceEditLink($contentUid),
        'editDcePopup',
        'height=768,width=1024,status=0,menubar=0,scrollbars=1',
    ], false)
]);

Example #2: preview page in frontend

$viewButton = $buttonBar->makeLinkButton()
    // @deprecated setOnClick
    ->setOnClick(BackendUtility::viewOnClick($pageUid, '', BackendUtility::BEgetRootLine($pageUid)))
    ->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
    ->setIcon($iconFactory->getIcon('actions-view-page', Icon::SIZE_SMALL))
    ->setHref('#');

Code block above being substituted with \TYPO3\CMS\Backend\Routing\PreviewUriBuilder based on ActionDispatcher capabilities, using :html`data-dispatch-action` and data-dispatch-args HTML attributes:

$previewDataAttributes = PreviewUriBuilder::create($pageUid)
    ->withRootLine(BackendUtility::BEgetRootLine($pageUid))
    ->buildDispatcherDataAttributes();
$viewButton = $buttonBar->makeLinkButton()
    // substituted with HTML data attributes
    ->setDataAttributes($previewDataAttributes ?? [])
    ->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
    ->setIcon($iconFactory->getIcon('actions-view-page', Icon::SIZE_SMALL))
    ->setHref('#');

Example #3: confirmation dialog

  • taken form extension news
  • see corresponding pull-request
  • side-note: There was a bug in extension news, examples below have been adjusted to show how the scenario probably would have been before, using confirm()
$pasteTitle = 'Paste from Clipboard';
$confirmMessage = GeneralUtility::quoteJSvalue('Shall we paste the record?');
$viewButton = $buttonBar->makeLinkButton()
    ->setHref($clipBoard->pasteUrl('', $this->pageUid))
    // @deprecated inline JavaScript requesting user confirmation
    ->setOnClick('return confirm(' . $confirmMessage . ')')
    ->setTitle($pasteTitle)
    ->setIcon($this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL));

Code block above being substituted with capabilities of modal dialog handling and functionalities of the Bootstrap framework.

$pasteTitle = 'Paste from Clipboard';
$confirmMessage = 'Shall we paste the record?';
$viewButton = $buttonBar->makeLinkButton()
    ->setHref($clipBoard->pasteUrl('', $this->pageUid))
    // using CSS class to trigger confirmation in modal box
    ->setClasses('t3js-modal-trigger')
    ->setDataAttributes([
        'title' => $pasteTitle,
        'bs-content' => $confirmMessage,
    ])
    ->setTitle($pasteTitle)
    ->setIcon($this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL));