Since TYPO3 CMS 7 it is possible to use RequireJS in the backend. A short explanation: RequireJS enables developers to have some kind of dependency handling for JavaScript. The JavaScript is written as so-called "Asynchronous Module Definition" (AMD). Some libraries delivered with TYPO3 are written as modules. This tutorial explains how you can write such modules on your own.
To be able to use RequireJS at all, some prerequisites must be fulfilled:
Resources/Public/JavaScript
directory. That directory is used for autoloadingFor this tutorial our extension name is foo_bar
and we name our module Wisdom
. So, create the file
typo3conf/ext/foo_bar/Resources/Public/JavaScript/Wisdom.js
.
The module's namespace is now TYPO3/CMS/FooBar/Wisdom
. As you can see, the extension name is upper camelcased.
Every AMD is wrapped in the same construct:
define([], function() {
});
This is the "container" of the module. It holds the module logic and takes care of dependencies.
Core-wise, TYPO3 itself defines in its own modules an object holding the module logic, namely parameters and methods. The object has the same name as the module, in our case "Wisdom":
define([], function() {
var Wisdom = {
sayings: [
'The quick brown fox jumps over the lazy dog',
'Pack my box with five dozen liquor jugs',
'The five boxing wizards jump quickly',
'Jackdaws love my big sphinx of quartz',
'How vexingly quick daft zebras jump',
'Bright vixens jump; dozy fowl quack'
]
};
Wisdom.say = function() {
alert(Wisdom.sayings[Math.floor(Math.random() * Wisdom.sayings.length)]);
};
});
The module is now enriched with some logic. But something is missing: We have to decide whether the module should be called when a page is loaded or it should be used in another module.
You may let the module run on load and return the object for further usage, but that is rather useless.
In any way, the missing part is a piece of cake. To let the module be a dependency of another module, add
return Wisdom;
To trigger the module after the page was loaded, add the ready
listener:
$(function() {
Wisdom.say();
});
The above code can be shortened by using $(Wisdom.say);
In the current state you may get a JavaScript error telling that "$ is undefined". This is correct, because $
is
unknown in this context, yet. Which leads to the "dependency" thing.
You may wonder what that empty array in define()
is all about. This array holds the modules that are loaded
beforehand. To get jQuery working, the line must be adjusted:
define(['jquery'], function($) {
But why was the $
parameter added to the function? Because the dependency array goes hand in hand with the parameter
list of the function, each dependency is accessible by the name passed as argument in the function. You might name the
parameter jq
, jQuery would be accessibly by jq
then.
Some libraries in the TYPO3 Core are loaded as dependency, but are not callable, because they e.g. extend jQuery. In such case, the libraries are at the end of the array and receive no parameter name.
define(['jquery', 'TYPO3/CMS/Backend/jquery.clearable'], function($) {
TYPO3/CMS/Backend/jquery.clearable
is now loaded as dependency, but is not callable, as there is no second parameter
in the function.
You may now write another module that uses our "Wisdom" module as dependency:
define(['jquery', 'TYPO3/CMS/FooBar/Wisdom'], function($, Wisdom) {
Please keep in mind that the "Wisdom" module in such case module return Wisdom
instead of using the ready event.
In case you use the ready event, you may wonder how to use the module. Answer: it depends!
If you use Fluid's f:be.pageRenderer
view helper, simply add the argument includeRequireJsModules
:
<f:be.pageRenderer
includeRequireJsModules="{
0:'TYPO3/CMS/FooBar/Wisdom'
}"
/>
However, if you don't use Fluid you may use PageRenderer
:
$pageRenderer = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Page\PageRenderer::class);
$pageRenderer->loadRequireJsModule('TYPO3/CMS/FooBar/Wisdom');
Bonus: loadRequireJsModule
takes a second argument $callBackFunction
which is executed right after the module was
loaded. The callback function must be wrapped within function() {}
:
$pageRenderer->loadRequireJsModule(
'TYPO3/CMS/FooBar/Wisdom',
'function() { console.log("Loaded Wisdom."); }'
);