3
\$\begingroup\$

I have recently started working on angular.js and I like it. I have decided to use a single controller per view. I use the json data from the backend. As my work is progressing, my codes are getting more verbose and I would like your suggestions on how I can (as a newbie) improve my code. I use the default $http service to fetch the JSON in my controller. But I don't want to repeat the same thing on all the other controller.

Can I use services or factories to call $http service and use them on all the controllers? At least some suggestions on reducing the number of lines in my code and making it more cleaner is very welcome.

Dashbord Controller

myApp.controller('KnobController', function($scope) {
    // to give dynamic behaviour for knobs using ng-repeat
    $scope.knobItems = {};
    $scope.knobItems.nums = [{
        knobTitle: "Company Profile",
        knobColor: "#f46607"
    }, {
        knobTitle: "Deals left This Month",
        knobColor: "#ffcc00"
    }, {
        knobTitle: "Pricelist",
        knobColor: "#f40787"
    }, {
        knobTitle: "Pictures",
        knobColor: "#a1b80a"
    }, {
        knobTitle: "Videos",
        knobColor: "#14b9d6"
    }];
});
// controller for knobs end here
myApp.controller('DashController', function($scope, $http, $cookies, $cookieStore) {
    $scope.sideToggle = function() {
        $(function() {
            $(".side-nav li:nth-child(2)").append("<img id='arrowRotate' src='images/prof_arrow1.png' data-swap='images/prof_arrow.png'>");
            $("#arrowRotate").click(function() {
                var _this = $(this);
                var current = _this.attr("src");
                var swap = _this.attr("data-swap");
                _this.attr('src', swap).attr("data-swap", current);
                //toggle li's below
                $(".side-nav li:nth-child(3)").toggle();
                $(".side-nav li:nth-child(4)").toggle();
                $(".side_nav_custom li:nth-child(2) a").toggleClass("orangeSwap");
            });
            // booking section modification
            $(".side-nav li:nth-child(10)").append("<img id='arrowBook' src='images/prof_arrow1.png' data-swap='images/prof_arrow.png'>");
            $("#arrowBook").click(function() {
                var _this = $(this);
                var current = _this.attr("src");
                var swap = _this.attr("data-swap");
                _this.attr('src', swap).attr("data-swap", current);
                //toggle li's below
                $(".side-nav li:nth-child(11)").toggle();
                $(".side_nav_custom li:nth-child(10) a").toggleClass("orangeSwap");
            });
        });
    };
    $scope.sideToggle();
    //line graph for chart.js goes here
    // Chart.js Data
    $scope.homeData = { /* data */
        labels: ["",
            "NOV", "DEC", "JAN", "FEB"
        ],
        datasets: [{
            strokeColor: "rgba(255.255,255,1)",
            pointColor: "rgba(159,209,154,1)",
            pointStrokeColor: "rgba(255,255,255,1.00)",
            data: [4.5, 8.8, 7.5, 9.5, 7.8, 9]
        }, ]
    }

    // Chart.js Options
    var step = 2;
    var max = 10;
    var start = 0;
    $scope.homeOptions = { /* options */
        scaleLabel: "<%= value + ' K ' %>",
        pointDot: false,
        bezierCurve: false,
        scaleOverride: true,
        scaleSteps: 10,
        // scaleStepWidth: Math.ceil(4/2),
        scaleSteps: Math.ceil((max - start) / step),
        scaleStepWidth: step,
        scaleStartValue: start,
        scaleShowGridLines: true,
        scaleGridLineWidth: 0,
        scaleGridLineColor: "rgba(0,0,0,0.1)",
        datasetFill: false,
        animation: true,
        animationSteps: 60,
        scaleFontColor: "#ffffff",
        scaleFontSize: 14,
        scaleLineColor: "rgba(255,255,255,1)",
        datasetStrokeWidth: 6,
        responsive: true
    };
    //chart.js for bar graph data
    // Chart.js Data
    $scope.hbarData = { /* data */
        labels: ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"],
        datasets: [{
            label: "My First dataset",
            fillColor: "rgba(31, 187, 166, 1)",
            // strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.75)",
            data: [50, 60, 55, 80, 60, 80, 60, 50, 70, 60, 80, 60]
        }, ]
    }

    // Chart.js Options
    $scope.hbarOptions = { /* options */
        scaleShowGridLines: false,
        showScale: true,
        scaleShowLabels: true,
        barShowStroke: true,
        scaleFontColor: "#d1d5d9",
        scaleShowLabels: false,
        scaleLineColor: "rgba(0,0,0,0)",
        responsive: true
    };
    $http({
        url: site + '/company/dashboard',
        method: "GET",
        transformRequest: encodeurl,
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    }).success(function(data) {
        console.log(data);
        $scope.count = data.count;
        $scope.reviews = data.reviews;
        $scope.market = data.stastics.market;
        $scope.visits = data.stastics;
        $scope.myData = data;
        $scope.custom = true;
    }).error(function(res) {
        console.log(res);
    });
});  

app.js

'use strict';
/**
 * @name servicepriceApp
 * @description
 * # servicepriceApp
 *
 * Main module of the application.
 */
var myApp;
(function() {
    myApp = angular
        .module('servicepriceApp', [
            'ngRoute',
            'ngCookies',
            'knob',
            'raty',
            'tc.chartjs'
        ])
        .config(function($routeProvider) {
            $routeProvider
                .when('/signup', {
                    templateUrl: 'views/signup.html',
                    controller: 'SignupController'
                })
                .when('/login', {
                    templateUrl: 'views/login.html',
                    controller: 'LoginController'
                })
                .when('/dashboard', {
                    templateUrl: 'views/dashboard.html',
                    controller: 'DashController'
                })
                .otherwise({
                    redirectTo: '/signup'
                });

        });
})();  

I was also wondering if it was a good idea to use separate controllers for knobs and sidetoggle.

\$\endgroup\$
1
\$\begingroup\$

To get dashboard data in different controllers you should move your $http service outside controller to factory, then in factory make function to query your server and store json data in object. Next you should include dashboardData factory in controller, or I would suggest to use instead ngRoute, ngRoute on steroid: ui.router and provide data to controller by resolve function: link.

Code refactoring by ui.router way:

app.js:

var myApp;
(function() {
    myApp = angular
        .module('servicepriceApp', [
            'ui.router',
            'ngCookies',
            'knob',
            'raty',
            'tc.chartjs'
        ])
        .config(function($stateProvider, $urlRouterProvider) {
            $stateProvider
                .state('signup', {
                    url: '/signup'
                    templateUrl: 'views/signup.html',
                    controller: 'SignupController'
                })
                .state('login', {
                    url: '/login'
                    templateUrl: 'views/login.html',
                    controller: 'LoginController'
                })
                .state('/dashboard', {
                    templateUrl: 'views/dashboard.html',
                    controller: 'DashController',
                    resolve: {
                      dashboardPromise: [
                        'dashboardData', function(dashboardData) {
                          return dashboardData.getDashboardData();
                        }
                      ]
                    }
                });
             $urlRouterProvider.otherwise('signup');
        });
})();

dashboardData factory o object is for e.g further inject new data.

myApp.factory('dashboardData', [
  '$http',
  function($http) {
    var o;
    o = {
      myData: []
    };
    o.getDashboardData = function() {
      return $http({
        url: site + '/company/dashboard',
        method: "GET",
        transformRequest: encodeurl,
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
        }
      }).success(function(data) {
        console.log(data);
        angular.copy(data, o.myData);
      }).error(function(res) {
        console.log(res);
      });
    };
    return o;
  }
]);

Controller Pass your dashboardData from state provider and then get data from object:

// controller for knobs end here
myApp.controller('DashController', function($scope, dashboardData, $cookies, $cookieStore) {

    $scope.count = dashboardData.myData.count;
    $scope.reviews = dashboardData.myData.reviews;
    $scope.market = dashboardData.myData.stastics.market;
    $scope.visits = dashboardData.myData.stastics;
    $scope.myData = dashboardData;
    $scope.custom = true;

    $scope.sideToggle = function() {
        $(function() {
            $(".side-nav li:nth-child(2)").append("<img id='arrowRotate' src='images/prof_arrow1.png' data-swap='images/prof_arrow.png'>");
            $("#arrowRotate").click(function() {
                var _this = $(this);
                var current = _this.attr("src");
                var swap = _this.attr("data-swap");
                _this.attr('src', swap).attr("data-swap", current);
                //toggle li's below
                $(".side-nav li:nth-child(3)").toggle();
                $(".side-nav li:nth-child(4)").toggle();
                $(".side_nav_custom li:nth-child(2) a").toggleClass("orangeSwap");
            });
            // booking section modification
            $(".side-nav li:nth-child(10)").append("<img id='arrowBook' src='images/prof_arrow1.png' data-swap='images/prof_arrow.png'>");
            $("#arrowBook").click(function() {
                var _this = $(this);
                var current = _this.attr("src");
                var swap = _this.attr("data-swap");
                _this.attr('src', swap).attr("data-swap", current);
                //toggle li's below
                $(".side-nav li:nth-child(11)").toggle();
                $(".side_nav_custom li:nth-child(10) a").toggleClass("orangeSwap");
            });
        });
    };
    $scope.sideToggle();
    //line graph for chart.js goes here
    // Chart.js Data
    $scope.homeData = { /* data */
        labels: ["",
            "NOV", "DEC", "JAN", "FEB"
        ],
        datasets: [{
            strokeColor: "rgba(255.255,255,1)",
            pointColor: "rgba(159,209,154,1)",
            pointStrokeColor: "rgba(255,255,255,1.00)",
            data: [4.5, 8.8, 7.5, 9.5, 7.8, 9]
        }, ]
    }

    // Chart.js Options
    var step = 2;
    var max = 10;
    var start = 0;
    $scope.homeOptions = { /* options */
        scaleLabel: "<%= value + ' K ' %>",
        pointDot: false,
        bezierCurve: false,
        scaleOverride: true,
        scaleSteps: 10,
        // scaleStepWidth: Math.ceil(4/2),
        scaleSteps: Math.ceil((max - start) / step),
        scaleStepWidth: step,
        scaleStartValue: start,
        scaleShowGridLines: true,
        scaleGridLineWidth: 0,
        scaleGridLineColor: "rgba(0,0,0,0.1)",
        datasetFill: false,
        animation: true,
        animationSteps: 60,
        scaleFontColor: "#ffffff",
        scaleFontSize: 14,
        scaleLineColor: "rgba(255,255,255,1)",
        datasetStrokeWidth: 6,
        responsive: true
    };
    //chart.js for bar graph data
    // Chart.js Data
    $scope.hbarData = { /* data */
        labels: ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"],
        datasets: [{
            label: "My First dataset",
            fillColor: "rgba(31, 187, 166, 1)",
            // strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.75)",
            data: [50, 60, 55, 80, 60, 80, 60, 50, 70, 60, 80, 60]
        }, ]
    }

    // Chart.js Options
    $scope.hbarOptions = { /* options */
        scaleShowGridLines: false,
        showScale: true,
        scaleShowLabels: true,
        barShowStroke: true,
        scaleFontColor: "#d1d5d9",
        scaleShowLabels: false,
        scaleLineColor: "rgba(0,0,0,0)",
        responsive: true
    };
});

I think that knobs and sidetoggle scope funtions should be in the same controllers as the views to which you want provide them, so I would not change it.

\$\endgroup\$
  • \$\begingroup\$ Thanks, this helps a lot. Will go through the link and see how it goes. \$\endgroup\$ – Thomas Sebastian Feb 16 '15 at 3:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.