Reputation: 2150
I want to pass some parameters for requirejs to start with like this:
<script src=".../require.min.js"
data-main="..../config.js"
data-modules="sticker datepicker">
</script>
It means I want to load the sticker
and datepicker
modules like this in config.js/main.js
var modules = modules_parameters.split(' ');
_.each(modules, function (m) {
var mod = require('...' + m);
mod.init(); // Sticker.init(), DatePicker.init()
});
The question is how can I get the modules_parameters
?
I can now use jquery like $('script[data-main]')
. But since apparently requirejs is scanning data-main
, did it expose an api to access the same <script>
tag?
background
I have a layout.html: <script src='require.js' data-main='config.js' data-modules='{placeholder}'>
and a page1.html to extend it: {placeholder}sticker datepicker{/placeholder}
and a page2.html to extend it: {placeholder}another another2{/placeholder}
so that each page loads its own modules.
Upvotes: 0
Views: 219
Reputation: 151401
I suggested in comments making module initialization be part of module instantiation. hbrlovehaku (the original asker) asked for more details. Comments are too constraining so I'm answering here.
The design in the original question suggests that a module like "datepicker" is defined like this:
define(function () {
function init() {
// Initialize here.
}
return {
init: init,
}
});
So then someone using a module like above must do:
define(["datepicker"], function (datepicker) {
datepicker.init();
});
That's because module instantiation and module initialization are decoupled. However, they don't have to be. The module can be defined like this:
define(function () {
// Initialize here
});
With the above design, the module is initialized as soon as another module requires it. Note that the function that is passed to define
is not executed until a module requires "datepicker". So a module using "datepicker" can be like this:
define(["datepicker"], function (datepicker) {
// There is no need to call init.
});
A page could then contain something like:
<script src="[...]/require.min.js" data-main="[...]/config.js"></script>
<script>
(function () {
var mods = "{placeholder}".split(" ");
// I don' know whether the anonymous function is necessary in the next line.
require(mods, function () {});
)();
</script>
Actually this little snippet above could be adapted for use even if an initialization function is necessary. Like this:
<script src="[...]/require.min.js" data-main="[...]/config.js"></script>
<script>
(function () {
var mods = "{placeholder}".split(" ");
require(mods, function () {
Array.prototype.forEach.call(arguments, function (mod) {
mod.init();
});
});
)();
</script>
{placeholder}
just needs to be replaced with actual module names, just like it would be in data-modules="{placeholder}"
Upvotes: 0
Reputation: 40298
In your RequireJS configuration, you can add a config
property and target the module that runs the initialization code:
require.config({
...
config: {
"app/config": {
initModules: ["sticker", "datepicker"]
}
}
...
});
Now from your app/config
module:
define(["underscore", "module"], function(_, module) {
var modules = module.config().initModules;
_.each(modules, function (m) {
// do your normal code here
});
});
This solution can cope for dynamically defined initModules
, if you do not mind rearranging your code a bit. What I usually do is put the RequireJS configuration separate from the main module. Then I have the chance to customize the configuration from an inline script (usually for language preferences):
<script src="scripts/require-cfg.js"></script>
<script>
require.config = require.config || {};
// the array below is dynamically generated (i.e. JSP, PHP, etc)
require.config["app/config"].initModules = ["sticker", "datepicker"];
</script>
<script src="scripts/lib/require.js"></script>
<script>
// bootstrap the application
require("app/main");
</script>
Not that for this case, require-cfg.js
would look like:
var require = {
paths: ...,
shim: ...,
config: ...
};
And not like require.config({...});
.
Upvotes: 1