Writing and Building AMD Modules in Moodle
How Moodle AMD modules work, how to structure them, how to inject Moodle services and strings, and how to produce minified build output with Grunt.
Moodle's AMD modules load JavaScript asynchronously and isolate dependencies using RequireJS. This guide covers module structure, injecting Moodle services, localization, and building production-ready minified output using Grunt.
SOP: Writing and Building AMD Modules in Moodle
This guide will walk you through creating, localizing, and building asynchronous module definition (AMD) JavaScript modules in Moodle, as well as how to pull in core Moodle services (like the notification system) from your AMD code.
1. What is AMD in Moodle?
Moodle uses RequireJS to load JavaScript modules asynchronously. An AMD module is a JavaScript file that:
- Declares its dependencies via a
define([...], function(...) { … })call. - Exports one or more functions (often a single
initentry point). - Can be minified and concatenated into production-ready code.
By using AMD, modules only load when needed and avoid polluting the global namespace.
2. Folder Layout
Inside your plugin (e.g. mod/assessmentform/), you should have:
mod/assessmentform/
├── amd/
│ ├── src/ ← Your unbuilt source files
│ │ └── survey_init.js
│ └── build/ ← Moodle's build step will place minified files here
│ └── survey_init.min.js
└── view.php ← Calls your AMD module via js_call_amd()
amd/src/Place your human-readable modules here.amd/build/After running the build, minified code will live here. Commit the build outputs so your plugin works without requiring Node on the production server.
3. Writing Your AMD Module
In amd/src/survey_init.js, you might have:
define([
'jquery',
'core/notification',
'core/str', // for translations
'survey-core',
'survey-js-ui'
], function($, notification, str, Survey) {
return {
init: function(args) {
// 1. Localization
var texts = args.str || {};
// str.get_string('key','mod_yourplugin') can also be used.
// 2. Load and render your SurveyJS
$.getJSON(args.jsonUrl).done(function(def) {
var survey = new Survey.Model(def);
survey.render(document.getElementById(args.containerId;
survey.onComplete.add(function(sender) {
// Build payload...
$.ajax({
url: args.postUrl,
method: 'POST',
data: JSON.stringify({ /* ... */ }),
contentType: 'application/json',
dataType: 'json',
}).done(function(response) {
notification.addNotification({
message: texts.responsesavedsuccess || 'Saved successfully!',
type: 'success'
});
// redirect ...
}).fail(function() {
notification.addNotification({
message: texts.responsefailed || 'Save failed.',
type: 'error'
});
});
});
}).fail(function() {
$('#'+args.containerId)
.html('<div class="alert alert-danger">Error loading form.</div>');
});
}
};
});
Key points
define([...], function(...) { … })List the module IDs you depend on. Moodle’s loader will map these to the right files.core/notificationExposesnotification.addNotification({message, type}).core/strOffersstr.get_string(key, component)for on-the-fly translations.js_call_amd()in PHPPass an associative array of arguments from PHP into your JS entry-point.
4. Injecting Moodle Services
Just list them in your dependency array:
define([
'jquery',
'core/notification',
'core/str',
'core/ajax',
// ...your other libraries...
], function($, notification, str, Ajax) {
// You now have `notification`, `str` and `Ajax.call()` available.
});
core/ajaxUse Moodle’s AJAX wrapper:Ajax.call([{methodname:'mod_yourplugin_do_something',args:{foo:1}}])[0].then(function(result){ … }).catch(function(err){ notification.exception(err);});
5. Localization
- In your language file (
lang/en/mod_assessmentform.php): $string['responsesavedsuccess']='Assessment saved successfully for {$a->fullname}.';$string['responsefailed']='Error saving assessment.';- Pass them into JS when you call your AMD module:
$PAGE->requires->js_call_amd('mod_assessmentform/survey_init','init',['str'=> ['responsesavedsuccess'=> get_string('responsesavedsuccess','mod_assessmentform'),'responsefailed'=> get_string('responsefailed','mod_assessmentform'),],// …other args…]);- In JS, access
args.str.responsesavedsuccess.
6. Building (Minifying) Your AMD
Moodle provides a Grunt setup out of the box. At your plugin root:
- Install tools (one-time per project):
npm install--globalgrunt-clinpm install- Build all AMD modules (including yours):
grunt amd- This reads every
amd/src/*.jsin all plugins, minifies them, and writes toamd/build/*.min.js. - You can also target just your plugin:
grunt amd:mod_assessmentform- Commit the contents of
amd/build/into your plugin’s repository.
If you prefer a standalone build, you can drop a Gruntfile.js at your plugin root that only references your AMD folder. Moodle’s core Gruntfile already handles this; there’s no extra setup needed.
7. Summary Checklist
- Create
amd/src/yourmodule.jswith adefine([...], ...). - Load it in PHP with:
$PAGE->requires->js_call_amd('mod_yourplugin/yourmodule','init',[$args]);- Use injected services:
core/notification→notification.addNotification(...)core/str→str.get_string(...)core/ajax→Ajax.call(...)- Build with
npm install && grunt amdand commitamd/build/*.min.js. - Test on your dev site, then deploy.
With this workflow in place, you can rapidly iterate your JS in amd/src/ and then generate production-ready, minified AMD modules via Moodle’s standard Grunt toolchain.
Solin specializes in Moodle plugin development and AMD module authoring.
Contact us