AngularJS - Understanding Isolate Scope

Let’s start off by creating an app named “choreApp” and a “kid” directive. The directive will be restricted to “E” with a template that’s just an input with ng-model=”chore” and displays chore after the input.

var app = angular.module('choreApp', []);

app.directive("kid", function() {
  return {
    restrict: "E",
    template: '<input type="text" ng-model="chore"> {{chore}}'
  };
});

Now we can use this kid directive in our app:

<div ng-app="choreApp">
  <kid></kid>
</div>

When we load the page we can type “clean your room” to tell the kid to clean his room, and the same message should be simply displayed right after. However, if you have multiple kids directives, like so:

<div ng-app="choreApp">
  <kid></kid>
  <kid></kid>
  <kid></kid>
  <kid></kid>
  <kid></kid>
</div>

Once we reload the page, if we type a chore into any of the input boxes, all of the kids are being told to do the same chore. This is because they’re all sharing the same scope at this point. What we need to do is isolate them so they don’t share the bindings. We can do this by setting the scope property on the object being returned in the “kid” directive.

app.directive("kid", function() {
  return {
    restrict: "E",
    scope: {},
    template: '<input type="text" ng-model="chore"> {{chore}}'
  };
});

Now we can go back and tell each kid a different chore, like “clean your room,” “wash the dishes,” and “take out the garbage,” and we see that the binding still works, but it’s limited to each individual directive we created. This, however, breaks any interaction with the controllers if the bindings we use are scoped in the controller. Let’s create a controller “ChoreCtrl” and set up some thing we’ll want to interact with. We’ll create a logChore function which takes a chore, and alerts ‘chore + “ is done!”’

var app = angular.module('choreApp', []);

app.controller("ChoreCtrl", function($scope){
  $scope.logChore = function(chore){
    alert(chore + " is done!");
  };
});

app.directive("kid" ...

Now we need to set up the controller in the view. We only need one kid for now, and we want the kid to invoke logChore when they’re done with their chore, so let’s also set the done attribute on the kid directive to “logChore(chore)”

<div ng-app="choreApp">
  <div ng-controller="ChoreCtrl">
    <kid done="logChore(chore)"></kid>
  </div>
</div>

Now we need to wire up logChore and done. We can do this by setting the done property on the scope object within the directive to an ampersand (&) for an expression (more will be covered on the different options) and then change the template to include a div with a class of "button" and an ng-click attribute set to "done({chore:chore})" and say "I'm done!" inside the div. The {chore:chore} syntax maps the chore from the model we made in the <input> to be passed to the logChore function when we said 'done="logChore(chore)"' (in the kid directive)

app.controller("ChoreCtrl", function($scope){
  $scope.logChore = function(chore){
    alert(chore + " is done!");
  };
});

app.directive("kid", function() {
  return {
    restrict: "E",
    scope: {
        done: "&"
      },
    template: '<input type="text" ng-model="chore">' +
      '{{chore}}' +
      '<div class="button" ng-click="done({chore: chore})">I\'m done</div>'
  };
});

Once we have this we can tell the kid “Clean your room” and when we hit “I’m done!” it should alert us with “Clean you room is done!”