typo3typo3-12.x

TYPO3 custom JavaScript module not loading in backend module


Using TYPO3 12.

I'm trying to add a JavaScript module to my backend module but I can't get it working.

Here is what I've done by following the official documentation on this:

  1. Register JS module in /Configuration/JavaScriptModules.php
return [
    'dependencies' => ['backend'],
    'imports' => [
        '@vendor/package/' => 'EXT:vendor/Resources/Public/JavaScript/',
    ],
];
  1. Providing PageRenderer to the module controller via /Configuration/Services.yaml
Vendeor\package\Controller\Backend\BackendModuleController:
    tags: ['backend.controller']
    arguments:
      $pageRenderer: '@TYPO3\CMS\Core\Page\PageRenderer'
  1. Using loadJavaScriptModule to add the JS module to the page
    public function initializeAction(): void
    {
        $this->pageRenderer->loadJavaScriptModule('@vendor/package/backend-module.js');
    }

I already tried alternatives like accessing the JavaScriptRenderer directly via the PageRenderer or using the f:be.pageRenderer ViewHelper but nothing seems to work.

I could also verify by debugging that the JS file gets added to the JavaScriptRenderer and is inside its importMap. I've also checked all file paths for possible typos multiple times now.

What am I missing here?


Solution

  • The solution: use ModuleTemplateFactory instead of TemplateView (extbase).

    Did not figure out why this does not work with the extbase approach but anyways, here are the steps to solve this:

    1. In your controller use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;

    2. add private readonly ModuleTemplateFactory $moduleTemplateFactory property to constructor

    3. in Configuration/Services.yaml add $moduleTemplateFactory: '@TYPO3\CMS\Backend\Template\ModuleTemplateFactory'

    4. in any action of your controller you can now do this:

    public function listAction(): ResponseInterface
        {
    
            $this->pageRenderer->loadJavaScriptModule('@vendor/package/backend-module.js');
            $data= $this->dataRepository->findAll();
    
            $moduleTemplate = $this->moduleTemplateFactory->create($this->request);
            $moduleTemplate->assign("data", $data);
    
            return $moduleTemplate->renderResponse();
        }
    

    And the JS file gets added to the module.

    Edit: Just note that this approach will also add some backend assets like the backend.css from the backend extension.