How to use directive properly in AngularJS

I am doing my first steps with directives on AngularJS and this directive is not working for me.

I have an ng-repeat list

<ul ng-after-list-filter>
    <li ng-repeat="item in items | filter:activeFilter.filterType = activeFilter.filterValue">...</li>
</ul>

that is being filtered with $scope.activeFilter.filterValue

I am trying to create the ng-after-list-filter directive so it will execute after the list has been filtered so I can make a dom manipulation on that new ul element.

This is my directive that is not working:

myModule.directive('ngAfterListFilter',function(){
    return {
        restrict: 'A',
        link: function(scope,element,attrs) {
            scope.$watch(scope.activeFilter.filterValue, function(val) {
                console.log('do something here');
            });
        }
    }
});
  1. How do I make it work? I assume that scope.activeFilter.filterValue is not being updated, but - it is in the scope, and it does get updated and the list gets filtered. and I am trying to watch on this variable so why isn't it working?

  2. Is there a better way to create this directive? I mean - I want to run a DOM changes when the list get updated (adjust sizes of things). so is there a way to listen to the $('ul').html()? I tried that but it outputs me an error that I put raw text in javascript

$last can be used to determine when the last <li> is being created. See this fiddle (I didn't write it) for an implementation of a checkLast directive that you can attach to your <li> element:

directive('checkLast', function () {
  return function (scope, element, attrs) {
     if (scope.$last === true) {
        element.ready(function () {
           // manipulate ul here, or if that doesn't work
           // try with $timeout:
           // $timeout(function() { 
           //    do manip here
           //}, 0, false);  // remove false if you need $apply to run

See also http://stackoverflow.com/a/13906907/215945

I'm not sure if element.ready() is necessary, or if it works on dynamically generated elements.

It seems like you want to reuse the filtered values from the filter? Correct?

If that's the case all you really need to do is this:

<!-- initial filter -->
<ul ng-after-list-filter>
    <li ng-repeat="item in filteredData =  (items | filter:activeFilter.filterType)">{{item}}</li>
</ul>

<!-- reuse what you filtered -->
<div ng-repeat="item in filteredData">{{item}}</div>

I wish I could take credit for this, but it's a trick I saw in another question on StackOverflow that I can't find now.

Then to know when this has been updated, you'd $watch the filteredData on the scope:

myModule.directive('ngAfterListFilter',function(){
    return {
        restrict: 'A',
        link: function(scope,element,attrs) {
            scope.$watch('filteredData', function(val) {
                console.log('do something here');
            });
        }
    }
});