Fragment

Jump to: navigation, search

Moodle 3.1


Introduction

fragment.js is an Asynchronous Module Definition (AMD) to allow the inclusion of rendered HTML code and associated JavaScript to be inserted through AJAX onto a page.

History

The issue for this was created to allow Moodle mforms to be changed and submitted via AJAX. Mforms currently do a lot of validation, and include accessibility code and tags. Most of Moodle uses these forms and there seemed no clear way to borrow or create another system that would satisfy all requirements.

fragment.js details

This JavaScript module is located at lib/amd/src/fragment.js

loadFragment is the exposed function to use. It takes four parameters.

  • component: The component for the callback that you will also supply. e.g. "mod_assign"
  • callback: The callback that you are calling.
  • contextid: The context ID for the component.
  • params: Parameters for the callback function.

This function returns a promise that is resolved with HTML and JavaScript.

This module will handle:

  • mforms
  • text editors
  • filters
  • fancy YUI modules such as editpdf.

Callback

The callback function needs to be located in {component}/lib.php

The function name should be in the following format - {component}_output_fragment_{callback}()

The callback function should return a string (HTML from a renderer).

example

The best example I can think of is a real example. The following code is taken from the first improvement to use this module. The following is for the assignment grading interface. Check out mod/assign/lib.php.

function mod_assign_output_fragment_gradingpanel($args) {
    global $CFG;
 
    $context = $args['context'];
 
    if ($context->contextlevel != CONTEXT_MODULE) {
        return null;
    }
    require_once($CFG->dirroot . '/mod/assign/locallib.php');
    $assign = new assign($context, null, null);
 
    $userid = clean_param($args['userid'], PARAM_INT);
    $attemptnumber = clean_param($args['attemptnumber'], PARAM_INT);
    $formdata = array();
    if (!empty($args['jsonformdata'])) {
        $serialiseddata = json_decode($args['jsonformdata']);
        parse_str($serialiseddata, $formdata);
    }
    $viewargs = array(
        'userid' => $userid,
        'attemptnumber' => $attemptnumber,
        'formdata' => $formdata
    );
 
    return $assign->view('gradingpanel', $viewargs);
}

For the JavaScript that accompanies this callback, have a look at mod/assign/amd/src/grading_panel.js

How it works

  1. The module fragment is included in a JavaScript file.
  2. When desired a call is made to the loadFragment function with various parameters including the name of the callback that will supply the rendered HTML.
  3. loadFragment makes an AJAX call to a web service core_get_fragment. This web service switches the requires manager class to a specific class (fragment_requirements_manager) for collecting all necessary JavaScript that is included in the html to be returned by the callback function. It also validates user access to the context (equivalent of calling require_login()) and then adds the context object to parameters as $args['context'] so the callback can do additional validation such as permission check.
  4. Now the callback is made and the function will generate the HTML. This HTML is returned to the web service.
  5. The web service collects all the JavaScript from the fragments_requirements_manager and sends back an array with both the HTML and JavaScript.
  6. The loadFragment function now checks the page to see if the JavaScript it has received has been loaded already. Only JavaScript that needs to be loaded is returned in the promise with the HTML.

fragments-extra.png

See also