MEAN Stack – AngularJS Scope & Controllers – Day 16

The MEAN Challenge Continues!

This video is part of the 30 Day MEAN Stack Honolulu Challenge

In this video we’ll break some code! We’ll look at the Customers Controller and break it up to support Create and Edit functions. We’ll also look at how we can remove the data-ng-init directive and use ‘Controller As’ to give our Controller an Alias.

We look at:
– The List Customers Page that was created from the Yeoman Generator
– Breaking the Customers Controller into 3 parts
– Using ‘this’ instead of ‘$scope’
– The use of the data-ng-init directive
– Removing the data-ng-init directive with ‘Controller As’
– Referring to a scope within our new Controller as an Alias

The functional design post mentioned in this video with the use case, storyboard and wireframes can be found here: Home Page Design.

9 Comments

Let me know what you think

  • martinroi
    Reply

    Hi Shristi,
    After changed one controller to three controllers, my list customers page does not work any more. There is an error says:
    TypeError: Cannot read property ‘query’ of undefined
    It seems Customers is undefined. But my code is same as yours, do you have any idea for the problem?
    The following is my code. Thanks in advance!

    ‘use strict’;
    var customersApp = angular.module(‘customers’);
    // Customers controller
    customersApp.controller(‘CustomersController’, [‘$scope’, ‘$stateParams’, ‘Authentication’, ‘Customers’,
    function($scope, $stateParams, $location, Authentication, Customers) {

    this.authentication = Authentication;
    // Find a list of Customers
    console.log( Customers );
    this.customers = Customers.query();
    }
    ]);
    customersApp.controller(‘CustomersCreateController’, [‘$scope’, ‘Customers’,
    function($scope, Customers) {
    }
    ]);
    customersApp.controller(‘CustomersEditController’, [‘$scope’, ‘Customers’,
    function($scope, Customers) {
    }
    ]);

    • bossable

      One thing that stands out is the order of your dependencies. Try removing ‘$location’ from your CustomersController: function($scope, $stateParams, $location, Authentication, Customers).
      Angular gets upset when the order or contents of the two parts of the Controller definition are different.

    • martinroi

      Thanks! It works!
      Your answer get me out of few hours comparison with your code. How dare I just overlook this difference! 🙂

    • bossable

      You’ll need to replace data-ng-init=”find()” with the ‘Controller As’ syntax to give Angular context of the Controller to use for the view.

  • bny
    Reply

    Hi Shristi,
    thank you for sharing!
    As an Angular noob I was just wondering what the whole benefit is by using ‘this’ instead of ‘$scope’?

    • bossable

      Good Question!

      In this video, I’ve used ‘this’ to help demonstrate the concept of $scope, but they are different things. I’ve gone down this path primarily for those people who have taken the Angular course over on codeschool (which follows the same convention http://campus.codeschool.com/courses/shaping-up-with-angular-js/intro).

      The Angular documentation seems to go back and forth between using ‘$scope’ and ‘this’. $scope is generally the accepted form, and is more powerful, especially when communicating between controllers.

      In the Angular documentation on this page: https://docs.angularjs.org/api/ng/directive/ngController , it has examples of both options, and states the following:

      -one binds methods and properties directly onto the controller using ‘this’: ng-controller=”SettingsController1 as settings”
      -one injects ‘$scope’ into the controller: ng-controller=”SettingsController2″

      The second option is more common in the Angular community, and is generally used in boilerplates. However, there are advantages to binding properties directly to the controller and avoiding scope.

      – Using ‘controller as’ makes it obvious which controller you are accessing in the template when multiple controllers apply to an element.
      – If you are writing your controllers as classes you have easier access to the properties and methods, which will appear on the scope, from inside the controller code.
      – Since there is always a ‘.’ in the bindings, you don’t have to worry about prototypal inheritance masking primitives.

    • bossable

      Here’s an example:

      Using $scope with multiple controllers:

      <div ng-controller="One">
        {{ name }}
        <div ng-controller="Two>
          {{ name }}
          <div ng-controller="Three">
            {{ name }}
          </div>
        </div>
      </div>
      
      Using 'Controller As' with multiple controllers:
      
      <div ng-controller="OneCtrl as one">
        {{ one.name }}
        <div ng-controller="TwoCtrl as two">
          Scope name: {{ two.name }}
          Parent name: {{ one.name }}
          <div ng-controller="ThreeCtrl as three">
            Scope name: {{ three.name }}
            Parent name: {{ two.name }}
            Grandparent name: {{ one.name }}
          </div>
        </div>
      </div>

      When we use $scope, and want to access the parent controller, we also need to include $parent calls.