Loading...
Area: Episerver B2B Commerce

Best practices for extending the website front end in Classic

Recommended reading 

The TypeScript has been built so all of the Angular services and controllers follow a pattern for event handlers and promises where they call onEvent, promiseCompleted and promiseFailed methods, which can be overridden. In the controllers, the completed method is passed the response.data and the failed method is passed the error.data which translates to the completed and failed methods are given the actual data returned from the HTTP call instead of the whole response object (which you do have access to in the services).

Code Sample: some.ts

protected initEvents(): void {
    this.$scope.$on("cartLoaded", (event: ng.IAngularEvent, cart: CartModel) => this.onCartLoaded(event, cart));
    this.settingsService.getSettings().then(
        (settings: core.SettingsCollection) => { this.getSettingsCompleted(settings); },
        (error: any) => { this.getSettingsFailed(error); });
}
protected getSettingsCompleted(settingsCollection: core.SettingsCollection): void {
    this.settings = settingsCollection.cartSettings;
    this.showInventoryAvailability = settingsCollection.productSettings.showInventoryAvailability;
    this.cartService.expand = "cartlines,costcodes";
    if (this.settings.showTaxAndShipping) {
        this.cartService.expand += ",shipping,tax";
    }
    this.cartService.getCart();
}
protected getSettingsFailed(error: any): void {
}
protected onCartLoaded(event: ng.IAngularEvent, cart: CartModel): void {
    this.displayCart(cart);
}

For example:

Code Sample: insite.cart.controller.ts

protected initEvents(): void {
    this.$scope.$on("cartLoaded", (event: ng.IAngularEvent, cart: CartModel) => this.onCartLoaded(event, cart));
    this.settingsService.getSettings().then(
        (settings: core.SettingsCollection) => { this.getSettingsCompleted(settings); },
        (error: any) => { this.getSettingsFailed(error); });
}
protected getSettingsCompleted(settingsCollection: core.SettingsCollection): void {
    this.settings = settingsCollection.cartSettings;
    this.showInventoryAvailability = settingsCollection.productSettings.showInventoryAvailability;
    this.cartService.expand = "cartlines,costcodes";
    if (this.settings.showTaxAndShipping) {
        this.cartService.expand += ",shipping,tax";
    }
    this.cartService.getCart();
}
protected getSettingsFailed(error: any): void {
}
protected onCartLoaded(event: ng.IAngularEvent, cart: CartModel): void {
    this.displayCart(cart);
}

This gives you specific override points so you don't have to copy and paste entire methods when you want to change what happens when a call comes back from the server or an event like the cart loaded event happens. Best practice, you should override that method, call super to execute the standard functionality, and put your customization before and after the call to super. For example your derived controller class:

Code Sample: Derived Controller Class

module insite.cart {
    "use strict";
    export class MyCartController extends CartController {
        protected getSettingsCompleted(settingsCollection: core.SettingsCollection): void {
            // Put customizations that should happen before standard code here
            super.getSettingsCompleted(settingsCollection);
            // Put customizations that should happen after standard code here
        }
    }
    // You must also change the registration in angular to use your version of the CartController
    angular
        .module("insite")
        .controller("CartController", MyCartController);
}

In the services, the completed and failed methods are passed the HTTP response object. For example:

Code Sample: insite.cart.service.ts

getCarts(filter?: IQueryStringFilter, pagination?: PaginationModel): ng.IPromise<CartCollectionModel> {
    return this.httpWrapperService.executeHttpRequest(
        this,
        this.$http({ method: "GET", url: this.serviceUri, params: this.getCartsParams(filter, pagination) }),
        this.getCartsCompleted,
        this.getCartsFailed
    );
}
protected getCartsParams(filter?: IQueryStringFilter, pagination?: PaginationModel): any {
    const params: any = filter ? JSON.parse(JSON.stringify(filter)) : {};
    if (pagination) {
        params.page = pagination.page;
        params.pageSize = pagination.pageSize;
    }
    return params;
}
protected getCartsCompleted(response: ng.IHttpPromiseCallbackArg<CartCollectionModel>): void {
}
protected getCartsFailed(error: ng.IHttpPromiseCallbackArg<any>): void {
}

In the Services we have also supplied an overridable method to control what parameters are passed to the HTTP call, in this case, the getCartsParams method. We are not doing anything in the getCartsCompleted or getCartsFailed methods, they are there as extension points and any errors are handled by the standard error interceptor.

Do you find this information helpful? Please log in to provide feedback.

Last updated: Dec 11, 2020

Recommended reading