Jan 15, 2017

Apply Mixin Pattern for AngularJs applications

We love single page applications with AngularJs. We always aim to create high performance apps with beautiful source code. A developer needs to write readable and maintainable code. Some features to evaluate: class hierarchies, directory hierarchies, design patterns.

Example of good directory hierarchy:

We never desire a file with too much lines. On our projects, a source file does not exceed 600 lines. We always split a large file into many small files. This habit is good to write maintainable code. A technique used to split file is applying the Mixin pattern.

The $controller service is responsible for instantiating controllers, so we use it to create the "inheritance" with angular.extend(). Every our Angular controllers initialize the authentication controller (named AuthController) as required. Every line of the the authentication controller embed to run first. We think this is a good design pattern.

var AuthController = function($auth, $scope, $http, $warning, $state, $stateParams) {
    $scope.isAuthenticated = function() {
        return $auth.isAuthenticated();

    $scope.logout = function() {
        if (!$auth.isAuthenticated());

    $scope.login = function() {
        var credentials = {
            email: $scope.email,
            password: $scope.password

            .then(function(res) {
                var loginModal = angular.element('#m_login');
                if (loginModal.hasClass('in')) {
                if ($stateParams.next) {
                    // logged in, redirect to next state
            .catch(function(res) {

And other controllers extend from the authentication controller. For example:

var EntryCollection = function($scope, $http, $controller, $rootScope, $warning) {
    angular.extend(this, $controller('AuthController', {$scope: $scope}));
    angular.extend(this, $controller('TagCollection', {$scope: $scope}));

    $scope.page_current = 1;
    $scope.paginate = function(page_index) {
            url: 'api/entry?page=' + page_index,
            method: 'GET'
        }).then(function(res) {
            $scope.entries = res.data.data;
            $scope.page_last = res.data.last_page;
            // save current page
            $scope.page_current = page_index;
        }, function(res) {
    // start paginating

No comments:

Post a Comment