Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS — injecting scope (without $) into a controller

In the Material Design mdDialog documentation, I’ve noticed that they’ve passed a scope (without a prefixed dollar sign) to the DialogController near the bottom.

(function(angular, undefined){
  "use strict";
  angular
   .module('demoApp', ['ngMaterial'])
   .controller('AppCtrl', AppController);
  function AppController($scope, $mdDialog) {
    var alert;
    $scope.showAlert = showAlert;
    $scope.showDialog = showDialog;
    $scope.items = [1, 2, 3];
    // Internal method
    function showAlert() {
      alert = $mdDialog.alert({
        title: 'Attention',
        content: 'This is an example of how easy dialogs can be!',
        ok: 'Close'
      });
      $mdDialog
        .show( alert )
        .finally(function() {
          alert = undefined;
        });
    }
    function showDialog($event) {
       var parentEl = angular.element(document.body);
       $mdDialog.show({
         parent: parentEl,
         targetEvent: $event,
         template:
           '<md-dialog aria-label="List dialog">' +
           '  <md-dialog-content>'+
           '    <md-list>'+
           '      <md-list-item ng-repeat="item in items">'+
           '       <p>Number {{item}}</p>' +
           '      '+
           '    </md-list-item></md-list>'+
           '  </md-dialog-content>' +
           '  <div class="md-actions">' +
           '    <md-button ng-click="closeDialog()" class="md-primary">' +
           '      Close Dialog' +
           '    </md-button>' +
           '  </div>' +
           '</md-dialog>',
         locals: {
           items: $scope.items
         },
         controller: DialogController
      });
      function DialogController(scope, $mdDialog, items) {
        scope.items = items;
        scope.closeDialog = function() {
          $mdDialog.hide();
        }
      }
    }
})(angular);

I've read that $ is a naming convention and a good way to make sure variables don't get overwritten. Why is this code failing to follow that convention? I.e in this context, how do we know when to use $ or not, and what is the significance? I believe in this case it must be more than just the naming convention, or the authors would have chosen to use $scope for purposes of consistency.

NOTE: I am aware of the difference between $scope and scope in linking functions, where scope is pointing to a fixed set of parameters. I do not believe that is why scope is used in this context, but feel free to let me know if I am wrong.

Thanks!

like image 233
nikk wong Avatar asked May 08 '15 06:05

nikk wong


1 Answers

I think the docs are inconsistent here - while being correct at the same time.

The scope and $scope here will be the same, but I only figured that out after reading the source code. The culprit line is inside InterimElement where locals are extended by options which in turn have a scope property.

 return showDone = compilePromise.then(function(compileData) {
              angular.extend(compileData.locals, self.options);

              element = compileData.link(options.scope);

I'm pretty sure that having $scope accessible as scope is only by incident and to keep things clean one should use $scope to refer to value provided by $injector like i.e. in controllers.

I've submitted a pull request to fix the inconsistency and compiled a pen demonstrating the usage.

like image 188
miensol Avatar answered Nov 16 '22 03:11

miensol