Exposing a directive's computed variable I have a directive called meetingList with its own isolated scope that receives a list of meetings and displays the filtered items based on some criteria. The controller for this directive holds two variables the meetingList and the filteredMeetingList. The scope where this directive is created needs to know how many items the directive is displaying (filteredMeetingList.length) in order to do something (outside the directive). I am currently exposing this variable using two way databinding on the isolated scope to send the variable outside.

Is there a better way of doing this? is there some kind of standard for this?

I set up a simple Plunker to illustrate the scenario.

HTML

  &lt;body ng-app="test"&gt;
    &lt;div ng-controller="AppCtrl as appCtrl"&gt;
      &lt;meeting-list meeting-list="appCtrl.meetingList" filtered-meetings-count="appCtr.filteredMeetingsCount"&gt;&lt;/meeting-list&gt;
      Total meetings {{appCtrl.meetingList.length}} &lt;br&gt;
      Meetings being displayed by the meetingList directive {{appCtr.filteredMeetingsCount}}
    &lt;/div&gt;
  &lt;/body&gt;


Javascript

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

  app.directive('meetingList', function(){
    return{
      restrict: 'E',
      scope: {
        meetingList: '=',
        //this is the variable that I use to expose the length of the filtered meetings to the external scope
        filteredMeetingsCount: '='
      },
      controller: function($scope){
        var self = this;
        var meetingList = $scope.meetingList;
        var filteredMeetingList = $scope.filteredMeetingList = [];

        filterMeetings();
        //Here I set the value after filtering
        $scope.filteredMeetingsCount = filteredMeetingList.length;
        function filterMeetings()
        {
          filteredMeetingList.push(meetingList[1]);
          filteredMeetingList.push(meetingList[2]);
        }

      },

      template: '&lt;div&gt;&lt;span ng-repeat="meeting in filteredMeetingList"&gt; {{meeting}} &lt;/span&gt;&lt;/div&gt;'
    }
  });

  app.controller('AppCtrl', function($scope){
    var self = this;
    self.meetingList = ["meeting1", "meeting2", "meeting3"];
  });
Given your code, it only filters the list and assigns the value on initialization. From the outside world, the count appears like a read-only value. This is ok... sort of.

One problem I see is that the count can be bound somewhere else and potentially manipulated. This potentially makes the count out of sync with the list count. Your list could say one thing, the count another. I don't know of any way to make it read-only. You could provide a function into the directive, sort of an onchange, where it gets called on modification in the directive and passes in the value there. This would mean that the controller holds responsibility of caching that value in a property. Just make sure that property also doesn't get manipulated though.

Another way you could improve this and avoid the 2-way binding "hack" is to move out the filtering to the enclosing controller. That way, the controller knows about the filtered list and it's length. All you have to do then is to provide that filtered list into your directive, since all it does is just render that list.

An even better way (I guess) is to move out the list and logic into a service/factory. That way, your "single source of truth" is a service, and not the controller nor directive. All you have to do then is pull in the data (full list and a filtered list) from the service/factory into the controller (controller will know about both), and pass in the filtered list to the directive. Any operations that manipulate the data lives in the service/factory, and done via function calls to it. It's essentially what React does with it's Flux architecture, isolating state and state changes into one location to prevent confusion caused by binding and multiple actors.