Note: You are currently viewing documentation for Moodle 3.7. Up-to-date documentation for the latest stable version of Moodle may be available here: Adrian Greeve/form comparison.

User:Adrian Greeve/form comparison

From MoodleDocs
< Adrian Greeve
Revision as of 02:40, 26 November 2015 by Adrian Greeve (talk | contribs) (→‎Form library and helper functions)
(Adrian Greeve/form comparison) Adrian Greeve/form comparison | Latest revision (diff) | Newer revision → (diff)

Edit form template

Form template
Type A Type B

{{!

   @template mod_lesson/page_editor

}}

<form action="">

Edit this Template:lessonpagetype

   {{#title}}
       {{>core/form-element-text}}
   Adrian Greeve/form comparison/title
Page Content
   {{#select}}    
       {{>core/form-element-select}}
   Adrian Greeve/form comparison/select    
       <button type="button" id="mod_lesson_editor_save_btn">Save</button>
       <button type="button" id="mod_lesson_editor_cancel_btn">Cancel</button>

</form>

Form data compilation for displaying

Form data compilation for display
Type A Type B

var frm = new form();

           frm.addFieldset('general', 'General');
           textfield = new text();
           textfield.set_name('title');
           textfield.set_id('mod_lesson_title_' + pageid);
           textfield.set_label('Page Title');
           textfield.set_required();
           textfield.set_text(lesson.pages[pageid].title);
           frm.addElement(textfield);
           selectfield = new selectElement();
           selectfield.set_name('Jump_1');
           selectfield.set_label('Jumps');
           selectfield.set_id("mod_lesson_jump_1_" + pageid);
           selectfield.set_options(joptions);
           frm.addElement(selectfield);
           $.when(frm.printForm()).then(function(tempformstuff) {
               $('.mod_lesson_pages').append(tempformstuff); 
               $('#mod_lesson_editor_save_btn').click(function() {
                   // Could do client side validation here.
                   if ($("#mod_lesson_title_" + pageid).val() == "") {
                       var textelement = $("#fitem_mod_lesson_title_" + pageid);
                       frm.handleError('title', textelement, 'text', 'Title should not be empty');
                   } else {
                       lesson.pages[pageid].save_edit_form(frm);
                   }
               });
               $('#mod_lesson_editor_cancel_btn').click(function() {
                   $('.mod_lesson_page_editor').remove();
               });
           });

var formdata = {

               lessonpagetype: lesson.pages[pageid].qtypestring,
               pageid: pageid,
               title: {
                   id: "mod_lesson_title_" + pageid,
                   label: "Page Title",
                   name: "title",
                   text: lesson.pages[pageid].title,
                   required: 1
               },
               contents: lesson.pages[pageid].contents,
               select: {
                   id: pageid,
                   label: "Jumps",
                   name: "Jump_1",
                   options: formfactory.formatOptions(joptions),
                   helpButton: "<button type=\"button\">Help is here</button>"
               }
           };
           $.when(templates.render('mod_lesson/page_editor', formdata)).done(function(pageeditor) {
               $('.mod_lesson_pages').append(pageeditor); 
               $('#mod_lesson_editor_save_btn').click(function() {
                   // Do client side validation.
                   var titleelement = $("#mod_lesson_title_" + pageid);
                   if (titleelement.val() == "") {
                       var errors = {
                           errors: {
                               name: "title",
                               message: "The lesson page title should not be empty"
                           }
                       };
                       formfactory.handleErrors(errors, formdata);
                   } else {
                       lesson.pages[pageid].save_edit_form(formdata);
                   }
               });
               $('#mod_lesson_editor_cancel_btn').click(function() {
                   $('.mod_lesson_page_editor').remove();
               });
           });

Saving a form

Form saving
Type A Type B

save_edit_form: function(formobject) {

           // Perhaps this could all be included in a save method for the form.
           var formdata = formfactory.getFormData();
           formdata["lessonid"] = lesson.id;
           formdata["pageid"] = this.id;
           delete formdata["Jump_1"];
           var promises = ajax.call([{
               methodname: 'mod_lesson_add_page',
               args: formdata
           }]);
           $.when.apply($.when, promises).then(function(response) {
               if (response.warnings.length != "0") {
                   formobject.handleErrors(response.warnings);
               }
           });

save_edit_form: function(formobject) {

           // Perhaps this could all be included in a save method for the form.
           var formdata = formfactory.getFormData();
           formdata["lessonid"] = lesson.id;
           formdata["pageid"] = this.id;
           delete formdata["Jump_1"];
           var promises = ajax.call([{
               methodname: 'mod_lesson_add_page',
               args: formdata
           }]);
           $.when.apply($.when, promises).then(function(response) {
               if (response.warnings.length != "0") {
                   formfactory.handleErrors(response.warnings, formobject);
               }
           });

New form elements

New form elements
Type A Type B

define(['jquery', 'core/form-element'], function($, formElement) {

   var Select = function() {
       formElement.call(this);
       this.type = 'select';
       this.options = ;
       this.template = "core/form-element-select";
   };
   /**
    * Format a normal array into an object for a select form element.
    *
    * @param {array} options An array of options.
    * @param {string} selected The selected option. Needs to match the array index.
    * @return {object} An options object that can be used with a select form element.
    */
   this.formatOptions = function(options, selected) {
       var returnoptions = [];
       var select = 0;
       if (selected !== 'undefined') {
           select = selected
       }
       for (index in options) {
           if (index == selected) {
               returnoptions.push({
                   value: index,
                   text: options[index],
                   selected: select
               });
           } else {
               returnoptions.push({
                   value: index,
                   text: options[index],
               });
           }
       }
       return returnoptions;
   }
   Select.prototype.set_name = function(name) {
       formElement.prototype.set_name.call(this, name);
   };
   Select.prototype.set_id = function(id) {
       formElement.prototype.set_id.call(this, id);
   };
   Select.prototype.set_label = function(label) {
       formElement.prototype.set_label.call(this, label);
   };
   Select.prototype.set_error = function(error) {
       formElement.prototype.set_error.call(this, error);
   };
   Select.prototype.set_required = function() {
       formElement.prototype.set_required.call(this);
   };
   Select.prototype.set_options = function(options, selected) {
       this.options = formatOptions(options, selected);
   };
   Select.prototype.get_name = function() {
       return formElement.prototype.get_name.call(this);
   };
   Select.prototype.show = function() {
       return formElement.prototype.show.call(this);
   };


   return Select;

});

Template for a select element

Same for both.

       <label {{#hiddenLabel}}class="accesshide"Adrian Greeve/form comparison/hiddenLabel for="Template:id">
           Template:label
           {{#required}}{{>core/form-required}}Adrian Greeve/form comparison/required
           {{#advanced}}{{>core/form-advanced}}Adrian Greeve/form comparison/advanced
       </label>
       {{{helpButton}}}

Form library and helper functions

Library
Type A Type B

define(['jquery', 'core/templates'], function($, templates) {

   var Form = function() {
       this._fieldsets = {};
       this.elements = {};
       this.formPage = ;
   };
   // These two methods would actually be using classes for the form.
   Form.prototype.add_top = function() {
this.formPage += '
<form action="">';
   };
   Form.prototype.add_bottom = function() {
this.formPage += '
<button type="button" id="mod_lesson_editor_save_btn">Save</button>'; this.formPage += '<button type="button" id="mod_lesson_editor_cancel_btn">Cancel</button>
</form>
';
   };


   Form.prototype.addFieldset = function(key, title) {
       this._fieldsets[key] = title;
   };
   Form.prototype.handleError = function(errorname, errorelement, elementtype, errormessage) {
       var index = elementtype + "-" + errorname;
       this.elements[index].set_error(errormessage);
       var htmlpromise = templates.render(this.elements[index].template, this.elements[index]);
       $.when(htmlpromise).then(function(newhtml) {
           templates.replaceNode(errorelement, newhtml);
       });
   }
   Form.prototype.handleErrors = function(errors) {
       // Need to loop through all potential errors.
       var errorname = errors.errors.name;
       var errorelementid = $(":input[name=" + errorname + "]").attr("id");
       // console.log(errorelementid);
       var errorelement = $("#fitem_" + errorelementid);
       // console.log(errorelement);
       // Get the form element type.
       var elementtype = errorelement.attr("data-field-type");
       Form.prototype.handleError.call(this, errorname, errorelement, elementtype, errors.errors.message);
   }


   Form.prototype.addElement = function(element) {
       var index = element.type + "-" + element.name;
       this.elements[index] = element;
   };
   Form.prototype.showElements = function() {
       console.log(this.elements);
   };
   Form.prototype.printForm = function() {
       var allpromises = [];
       for (index in this.elements) {
           allpromises.push(this.elements[index].show());
       }
       return $.when.apply($.when, allpromises).then(function() {
           Form.prototype.add_top.call(this);
           var schema = arguments;
           for (index in schema) {
               this.formPage += schema[index][0];
           }
           Form.prototype.add_bottom.call(this);
           return this.formPage;
       }, function() {
          return 'default html'; 
       });
   }
   return Form;

});

define(['jquery', 'core/templates'], function($, templates) {

   var formData;
   return {
       handleErrors: function(errors, formdata) {
           // name attribute of the error.
           var errorname = errors.errors.name;
           var templatedata;
           for (index in formdata) {
               if (typeof formdata[index] == "object") {
                   if (formdata[index].name == errorname) {
                       formdata[index].error = errors.errors.message;
                       templatedata = formdata[index];
                   }
               }
           }
           // for (index in errors.errors) {
           //     console.log(errors.errors["name"]);
           // }
           // Need to loop through all potential errors.
           var errorelementid = $(":input[name=" + errorname + "]").attr("id");
           // console.log(errorelementid);
           var errorelement = $("#fitem_" + errorelementid);
           // console.log(errorelement);
           // Get the form element type.
           var elementtype = errorelement.attr("data-field-type");
           // console.log(elementtype);
           var template = 'core/form-element-' + elementtype;
           var templatepromise = templates.render(template, templatedata);
           $.when(templatepromise).then(function(newhtml) {
               templates.replaceNode(errorelement, newhtml);
           });
       },
       getFormData: function() {
           formData = $('form').serializeArray();
           var tempstorage = {};
           for (index in formData) {
               var name = formData[index].name;
               if (name !== 'query') {
                   tempstorage[name] = formData[index].value;
               }
           }
           return tempstorage;
       },
       /**
        * Format a normal array into an object for a select form element.
        *
        * @param {array} options An array of options.
        * @param {string} selected The selected option. Needs to match the array index.
        * @return {object} An options object that can be used with a select form element.
        */
       formatOptions: function(options, selected) {
           var returnoptions = [];
           var select = 0;
           if (selected !== 'undefined') {
               select = selected
           }
           for (index in options) {
               if (index == selected) {
                   returnoptions.push({
                       value: index,
                       text: options[index],
                       selected: select
                   });
               } else {
                   returnoptions.push({
                       value: index,
                       text: options[index],
                   });
               }
           }
           return returnoptions;
       }
   };

});

Simple web service

class mod_lesson_external extends external_api {

   public static function add_page_parameters() {
       return new external_function_parameters(
           array(
               'lessonid' => new external_value(PARAM_INT, 'lesson module ID'),
               'pageid' => new external_value(PARAM_INT, 'lesson page ID'),
               'title' => new external_value(PARAM_TEXT, 'lesson page title', VALUE_OPTIONAL)
           )
       );
   }
   public static function add_page($lessonid, $pageid, $title) {
       $params = self::validate_parameters(self::add_page_parameters(),
               array($lessonid, $pageid, $title));
       $errors = array();
       if (empty($title)) {
           $errors["code"] = "formvalidationfailed";
           $errors["message"] = "Validation Failed";
           $errors["errors"] = array('code' => 'notitlefound', 'name' => 'title', 'message' => 'Title must not be empty');
           return array('status' => false, 'warnings' => $errors);
       }
       return array('status' => true, 'warnings' => $errors);
   }
   public static function add_page_returns() {
       return new external_single_structure(
           array(
               'status' => new external_value(PARAM_BOOL, 'status: true if success'),
               'warnings' => new external_warnings()
           )
       );
   }

}