3

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

Alon
  • 7,618
  • 18
  • 61
  • 99
  • You have only one equals in your filter directive; hopefully that's a typo and you meant ==? – Kato Jul 12 '13 at 22:17

2 Answers2

7

$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 https://stackoverflow.com/a/13906907/215945

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

Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
0

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');
            });
        }
    }
});
Ben Lesh
  • 107,825
  • 47
  • 247
  • 232
  • I don't understand why to duplicate the list? now I have 2 lists instead of one and I still don't know how to trigger a function when the list has finished changing. – Alon Jan 31 '13 at 13:59
  • Oh, sorry, I didn't understand your question I guess. If you need to know when the list is filtered, you could add a $watch to the `filteredData` parameter above. – Ben Lesh Jan 31 '13 at 14:05