nikk wong
nikk wong

Reputation: 8670

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!

Upvotes: 6

Views: 993

Answers (2)

Mateus AJ Leon
Mateus AJ Leon

Reputation: 1382

This isn't a failure over the convention, not even a failure on the snippet you got to use the modal.

The use of scope, and not $scope, it's to avoid overwrite vars inside the nested function.

The choice to place the scope without a dolar sign its to avoid errors for whom that will get the snippet.

Separating things, using Controller as syntax, for example, can help clear things up.

Upvotes: 0

miensol
miensol

Reputation: 41638

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.

Upvotes: 5

Related Questions