...
- 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 should be defined camel case and assign observable / observableArray based on requirements. it would start _that / _self scope variables.
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(); 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();
...
$.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 deferred.resolve(data), defer.reject and defer.promise().
- Service's fails case should be handled properly and write a meaningful error message based on the frontend error message requirement. We have handled three different way error messages.
- Error log in browsers console : Console.info("error message"); Console.error("error message");
- Frontend side 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: Read ---------- confluence page.
...