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)
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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()
           )
       );
   }

}