Moodle Mobile 2 (Ionic 1) Developing a plugin tutorial
- Moodle Mobile 2 (Ionic 1) Customization
- Setting up your development environment for Moodle Mobile 2 (Ionic 1)
- Moodle Mobile development using Chrome or Chromium
- Moodle Mobile 2 (Ionic 1) Plugins Development
- Moodle Mobile 2 (Ionic 1) Themes
- Moodle Mobile 2 (Ionic 1) Developing a plugin tutorial
- Moodle Mobile 2 (Ionic 1) Developing a plugin tutorial part 2
- Moodle Mobile debugging WS requests
- Moodle Mobile 2 (Ionic 1) Remote add-ons
- Moodle Desktop
- Moodle Mobile FAQ
- Moodle Mobile End To End Testing
- See all Moodle App pages
- See pages for Moodle App Ionic 5 (current)
- See pages for Moodle App Ionic 3 (legacy)
- See pages Moodle App Ionic 1 (legacy)
- See pages for Moodle App Phonegap (legacy)
For user documentation see Moodle Mobile
Warning: This page is no longer in use. The information contained on the page should NOT be seen as relevant or reliable. |
Warning: This page is no longer in use. The information contained on the page should NOT be seen as relevant or reliable. |
IMPORTANT: This documentation will be obsolete in May 2018, please read this announcement.
Introduction
This tutorial describes all the steps needed for developing an add-on for the Moodle Mobile app.
In this tutorial we make the following assumptions:
- You have a medium/good skills/understand of AngularJS/Ionic, PHP and Moodle architecture
- You know what a Web Service is and how it works in Moodle
- The plugin you are going to develop requires a Web Service in your Moodle installation to work
There is a second part of this tutorial where we extend the add-on features Moodle Mobile Developing a plugin tutorial part 2
Add-on spec
We want to develop a plugin that will display a new button in the user profile for adding new notes to the user. This plugin is suitable for course managers of teachers.
A couple of screenshots with the desired result:
Steps
Set up your development environment
Please, read Setting up your development environment for Moodle Mobile 2
Set up your Moodle installation
Enable debugging, disable caches, etc... the typical settings for developing.
Enable the Mobile Service via Admin / Plugins / Web Services / Mobile
Develop the Moodle Web Services you are going to need
In this case we'll use an existing web service (core_notes_create_notes) that is already available in the Moodle Mobile app service, if you need custom functions you will need to develop a local plugin including there your new Web Services (see https://moodle.org/plugins/view/local_wstemplate) and create a custom service.
Develop the Moodle Mobile add-on
The full source code can be found here: https://github.com/moodlehq/moodlemobile2/tree/master/www/addons/notes
www/addons/notes/main.js
angular.module('mm.addons.notes', [])
.run(function($mmUserDelegate, $mmaNotesHandlers) {
$mmUserDelegate.registerPlugin('mmaNotes:addNote', $mmaNotesHandlers.addNote);
});
Here we declare the plugin, and register the Plugin (this means that the plugin will be displayed in the User profile.
We will use the $mmaNotesHandlers service for holding all the code related to the plugin availability and main functions
There are more delegates for registering your plugin, see:
- www/addons/mod_forum/main.js (Module delegate, and module actions delegate)
- www/addons/messages/main.js (Main side menu delegate, and multiple delegates for the user profile)
www/addons/notes/services/handlers.js
self.isEnabled = function() {
return $mmaNotes.isPluginEnabled();
};
self.isEnabledForUser = function(user, courseId) {
// Active course required.
return courseId && user.id != $mmSite.getUserId();
};
These are mandatory functions that will check our plugin availability, the first one will rely in the $mmaNotes service (isPluginEnabled function), the second ones checks that the user profile is being viewed inside a course (because the WS requires it) and that the current user is not the required user (so you don't see the buttons in your own profile).
self.getController = function(user, courseid) {
return function($scope) {
// Button title.
$scope.title = 'mma.notes.addnewnote';
$ionicModal.fromTemplateUrl('addons/notes/templates/add.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(m) {
$scope.modal = m;
});
$scope.closeModal = function(){
$scope.modal.hide();
};
$scope.addNote = function(){
// Freeze the add note button.
$scope.processing = true;
$mmaNotes.addNote(user.id, courseid, $scope.note.publishstate, $scope.note.text).then(function() {
$translate('mma.notes.eventnotecreated').then(function(str) {
$ionicLoading.show({
template: str,
duration: 2000
});
});
}, function(error) {
$mmUtil.showErrorModal(error);
}).finally(function() {
$scope.closeModal();
});
};
$scope.action = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.note = {
publishstate: 'personal',
text: ''
};
$scope.processing = false;
$scope.modal.show();
};
};
};
These is the main function code, it does the following:
- $scope.title = 'mma.notes.addnewnote'; This sets the button title, note that we reference to the addnewnote string that is in the www/addons/notes/lang/en.json file (we need to prefix the string id to identify the plugin)
- $ionicModal.fromTemplateUrl - Creates the modal we are going to use for displaying the form, the HTML code of the form is in www/addons/notes/templates/add.html
- $scope.closeModal - Helper function for closing the modal inside the modal via a button
- $scope.addNote - This function will be called when the user clicks the "Add a note" button in the modal, it will use the $mmaNotes service that handles all the logic WS logic for creating the note
- $scope.action - This function will be called when the user clicks the "Add a note" button in the user profile view, it will open the modal and set the default values
www/addons/notes/services/notes.js
angular.module('mm.addons.notes')
.factory('$mmaNotes', function($mmSite, $log, $q) {
$log = $log.getInstance('$mmaNotes');
var self = {};
self.addNote = function(userId, courseId, publishState, noteText) {
var data = {
"notes[0][userid]" : userId,
"notes[0][publishstate]": publishState,
"notes[0][courseid]": courseId,
"notes[0][text]": noteText,
"notes[0][format]": 1
};
return $mmSite.write('core_notes_create_notes', data);
};
self.isPluginEnabled = function() {
var infos;
if (!$mmSite.isLoggedIn()) {
return false;
} else if (!$mmSite.canUseAdvancedFeature('enablenotes')) {
return false;
} else if (!$mmSite.wsAvailable('core_notes_create_notes')) {
return false;
}
return true;
};
return self;
});
This file contains the notes service:
- isPluginEnabled - Checks if the notes functionality is available by checking Moodle settings and the required WS availability
- addNote - Will call the remote WS for adding the note via the $mmSite.write helper method (the $mmService has also a read method for retrieving data)
/www/addons/notes/templates/add.html
<ion-modal-view class="product edit create">
<form name="itemEdit" ng-submit="addNote()">
<ion-header-bar class="bar-header">
<h1 class="title">{{ 'mma.notes.addnewnote' | translate }}</h1>
<a class="button" ng-click="closeModal()">{{ 'mm.core.cancel' | translate }}</a>
</ion-header-bar>
<ion-content has-bouncing="true">
<div class="row">
<div class="col">
<label class="item item-input item-select">
<div class="input-label">
{{ 'mma.notes.publishstate' | translate }}
</div>
<select ng-model="note.publishstate" name="publishstate">
<option value="personal">{{ 'mma.notes.personalnotes' | translate }}</option>
<option value="course">{{ 'mma.notes.coursenotes' | translate }}</option>
<option value="site">{{ 'mma.notes.sitenotes' | translate }}</option>
</select>
</label>
</div>
</div>
<div class="row">
<div class="col">
<label class="item item-input text">
<textarea placeholder="{{ 'mma.notes.note' | translate }}" rows="5" ng-model="note.text" name="text" lose-focus-on-return required="required"></textarea>
</label>
</div>
</div>
<div class="padding">
<button type="submit" class="button button-block" ng-disabled="processing || !note.text.length || note.text.length < 2">
{{ 'mma.notes.addnewnote' | translate }}
</button>
</div>
</ion-content>
</form>
</ion-modal-view>
This file includes the code for the modal. As you can see the close button will call the closeModal() function meanwhile the Add a note button will submit the form that will invoke the addNote function
For more information, refer to http://ionicframework.com/docs/api/service/$ionicModal/