If you have a comment on this topic, contact Aptify Documentation. If you want to return to the Aptify Community Site, please click here.

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 8 Next »

Prerequisite for building new or extending existing controls.

 Control level guidelines and code review standards with examples.

  • A control should have one javascript file and one HTML template file with the same name.
    example: html/BillingShippingAddress.html and js/BillingShippingAddress.js

  • A control's name should unique and meaningful and should not duplicate.
    example: BillingShippingAddress.html and BillingShippingAddress.js

  • A javascript variable will be created that will act as a collection for all of the controls objects. 
    example : var eb_billingShippingAddress = eb_billingShippingAddress || {};

  • Control's properties, functions and methods name should start with came case.
    example: productCatalogPage

  • Any object at the collection level should be generic to all instances of that control. Instance-specific information should live at the model level. SitePath, TemplatePath and ServicePath would be fixed properties for each control. These variables should be prefixed with an eb_prefix so that it does not collide with other JavaScript systems.
    example : 
    eb_billingShippingAddress.SitePath = eb_Config.SitePath;
    eb_billingShippingAddress.TemplatePath = "html/BillingShippingAddress.html";
    eb_billingShippingAddress.ServicePath = eb_Config.ServicePath;

  • The Path of the HTML template should mirror that of the path to the JS.
    example: eb_billingShippingAddress.TemplatePath = "html/BillingShippingAddress.html";

  • Each model's properties / field should be defined camel case and assign to ko.observable / ko.observableArray / ko.computed based on logic. 
    example: 
       var _that = this;
     _that.domElement = options.domElement;

    _that.showError = ko.observable(0);
    _that.errorMessage = ko.observable();
    _that.showSuccess = ko.observable(0);
    _that.successMessage = ko.observable();
    _that.billingAddress = ko.observableArray();

  • Should not use 'this' object directly in function. It should use var _self = this;
  • Each model's function's name should be meaningful and scope should be model's context.
    example:

    _that.toggleShipping = function () {
    _that.shippingAddressCollapse(!_that.shippingAddressCollapse());
    };

 

  • If there is more than one model for a control, a collection called models will be added to the control collection.
  • Sitewide settings such as the dom, service data, template path and dependent objects etc. will be passed into the control's javascript collection at the time of model creation.
    example : 

    eb_billingShippingAddress.model = function (options) {
    var _that = this;........}

  •  A render function should exist on each control.
    • Its job is to grab the template and insert it into a dom element that is passed into the function.
    • It should accept a user-supplied template in the place of the default template.

example: 

eb_billingShippingAddress.render = function (options) {
var defer = jQuery.Deferred();

if (!options) {
throw { type: "argument_null", message: "An object with values in the templatePath and domElement properties is required.", stack: Error().stack };
}

if (!options.templatePath) {
var finalPath = eb_billingShippingAddress.SitePath + eb_billingShippingAddress.TemplatePath;
options.templatePath = finalPath;
}

if (!options.domElement) {
throw { type: "argument_mismatch", message: 'Missing domElement. The object passed in must have a domElement property with a non-empty DOM object.', stack: Error().stack };
}

$.get(options.templatePath).done(function (data) {
options.domElement.innerHTML = data;
defer.resolve(data);
}).fail(defer.reject);
return defer.promise();
};

 

  • GET service call method should be control leve with parameters and deferred object handling.
    example: 

    eb_billingShippingAddress.createAddressRecord = function (data, personId) {
    var defer = jQuery.Deferred();
    console.info('create address record...');

    if (!personId || personId <= 0) {
    throw { type: "argument_null", message: "personId property is required.", stack: Error().stack };
    }
    if (!data) {
    throw { data: "argument_null", message: "data property is required.", stack: Error().stack };
    }
    var service = eb_billingShippingAddress.newAddressService.replace("{personId}", personId);

    $.ajax({
    url: service,
    crossDomain: true,
    type: "POST",
    data: data,
    xhrFields: {
    withCredentials: true
    }
    }).done(function (result) {
    defer.resolve(result);
    }).fail(defer.reject);
    return defer.promise();
    };

  • PATCH service call method should be control leve with parameters and deferred object handling.
    example: 

    eb_billingShippingAddress.updateProfileAddressRecord = function (data, addressName, personId) {
    var defer = jQuery.Deferred();
    if (!personId || personId <= 0) {
    throw { type: "argument_null", message: "personId property is required.", stack: Error().stack };
    }

    if (!addressName) {
    throw { type: "argument_null", message: "addressName property is required.", stack: Error().stack };
    }

    if (!data) {
    throw { data: "argument_null", message: "data property is required.", stack: Error().stack };
    }

    console.info('update address...');
    var service = eb_billingShippingAddress.updateProfileAddressService.replace("{personId}", personId).replace("{addressName}", addressName);
    $.ajax({
    url: service,
    type: "PATCH",
    contentType: "application/json",
    data: JSON.stringify(data),
    xhrFields: {
    withCredentials: true
    }
    }).done(function (result) {
    defer.resolve(result);
    }).fail(defer.reject);
    return defer.promise();
    };

  • POST service call method should be control leve with parameters and deferred object handling.
    example: 

    eb_billingShippingAddress.createAddressRecord = function (data, personId) {
    var defer = jQuery.Deferred();
    console.info('create address record...');

    if (!personId || personId <= 0) {
    throw { type: "argument_null", message: "personId property is required.", stack: Error().stack };
    }
    if (!data) {
    throw { data: "argument_null", message: "data property is required.", stack: Error().stack };
    }
    var service = eb_billingShippingAddress.newAddressService.replace("{personId}", personId);

    $.ajax({
    url: service,
    crossDomain: true,
    type: "POST",
    data: data,
    xhrFields: {
    withCredentials: true
    }
    }).done(function (result) {
    defer.resolve(result);
    }).fail(defer.reject);
    return defer.promise();
    };

  • DELETE service call method should be control leve with parameters and deferred object handling.
    example:

    eb_billingShippingAddress.deletePersonAddressRecord = function (addressName, personId) {
    var defer = jQuery.Deferred();
    if (!personId || personId <= 0) {
    throw { type: "argument_null", message: "personId property is required.", stack: Error().stack };
    }

    if (!addressName) {
    throw { type: "argument_null", message: "addressName property is required.", stack: Error().stack };
    }

    console.info('delete address...');
    var service = eb_billingShippingAddress.deletePersonAddressService.replace("{personId}", personId).replace("{addressName}", addressName);

    $.ajax({
    url: service,
    type: "DELETE",
    xhrFields: {
    withCredentials: true
    }
    }).done(function (result) {
    defer.resolve(result);
    }).fail(defer.reject);
    return defer.promise();
    };

  • Each service call should have handled with Jquery Deferred object with proper use of resolve(), reject() and promise() methods.
  • Service's fails case should be handled properly and write an appropriate meaningful error message based on the control requirements. We have handled three different way error messages.  
    • Error log in browsers console : Console.info("error message") and  Console.error("error message"); 
    • Control level predefined error messages under the knownResponses method :  _that.errorMessage(eb_billingShippingAddress.knownResponses[2].message);
    • Error message from service side: _that.errorMessage(data.responseJSON.message);

  • Knockout validations: https://github.com/Knockout-Contrib/Knockout-Validation

  • The control will know the default relative path to its HTML and it will be declared in a variable in the collection.
  • YUIDoc comments should be used and should be meaningful information that developers can use to understand what a function is doing.
  • Instance initiation should not happen at the control level.
  • References to JS objects outside of the scope of the control should be avoided.
  • It should only take 1 call to the server to get all of the initial data to show to the user.
  • Controls will be loaded asynchronously by the browser in whatever order the browser chooses.

Page level guidelines with examples.

  1. Need to define div element with ID attribute for loading control on the html page.
  2. Code should write $(document).ready (function () {} block.
    1. We should avoid use of ID attribute in HTML template file.
    2. Control should load with required configuration. We should use the eb_Config setting for the class name.
  3. Example:

                 var options = {}

                options.domElement = $('#productCatalog')[0];

                options.templatePath = "/html/ProductCatalog.html";

                eb_Config.config(options, eb_productCatalog);

     

      eb_productCatalog.render(options).done(function(){

                    eb_productCatalog.live = new eb_productCatalog.productModel(undefined, options.domElement);

                    ko.applyBindings(eb_productCatalog.live, eb_productCatalog.live.domElement);//Apply KO bindings, fire up the control

      });

  4. Control dependencies will be passed into the control when an instance is created.
  • References to all of the Javascript and CSS needed should be loaded at the page level.
  • Control models should be instantiated at the page level inside of a document. ready jQuery object.
  • Instances of the control's model should be added to that controls collection for reference. ex. ebLogin.live
  • Site-wide settings should be loaded and passed into the controls at the page level. This eliminates the dependency to the config file at the time the files are being loaded.

Sitewide guidelines with examples.

  • Sitewide settings should live in the sitewide configuration file.

 

  • No labels