Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Moodle Mobile 2 (Ionic 1) Developing a plugin tutorial

From MoodleDocs


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:

Initial view
Course contents view

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 plugin

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">

Template:'mma.notes.addnewnote'

           <a class="button" ng-click="closeModal()">Template:'mm.core.cancel'</a>
       </ion-header-bar>
       <ion-content has-bouncing="true">
                   <label class="item item-input item-select">
                       <select ng-model="note.publishstate" name="publishstate">
                           <option value="personal">Template:'mma.notes.personalnotes'</option>
                           <option value="course">Template:'mma.notes.coursenotes'</option>
                           <option value="site">Template:'mma.notes.sitenotes'</option>
                       </select>
                   </label>
                   <label class="item item-input text">
                       <textarea placeholder="Template:'mma.notes.note'" rows="5" ng-model="note.text" name="text" lose-focus-on-return required="required"></textarea>
                   </label>
               <button type="submit" class="button button-block" ng-disabled="processing || !note.text.length || note.text.length < 2">
                   Template:'mma.notes.addnewnote'
               </button>
       </ion-content>
   </form>

</ion-modal-view>

See also

Moodle Mobile Developing a plugin tutorial part 2