3

I have a utility function notNull() intended to be used with filters like so:

 ...| filter:notNull()"

I need it in more directives and that's why I placed it in $rootScope.

The problem is that my filter isn't called.I created a sample plnkr:

http://plnkr.co/edit/Nq0iLw?p=preview

Can someone help? why isn't the filter called and not filtering my items?

PS. this expression in the filter doesn't seam to work for nulls :

 ...| filter:{myProp:!null}
2
  • Why not just create a filter? Commented Oct 31, 2013 at 12:33
  • because I need the extra functionality of the default filter .I just want to plug in my comparator Commented Oct 31, 2013 at 12:45

1 Answer 1

4

[Note: Updates arranged in reverse chronological order.]

UPDATE 2

First, to answer your question "why does ...| filter:{myProp:!null} not work:
It is because the syntax you are trying to use is (according to the docs) applicable only to string values (and null is not a string value).

You could create (and attach to your app) a custom filter:

app.filter("notEqual", function() {
    return function(items, key, value) {
        var filtered = [];
        items.forEach(function(item) {
            if (item && (item[key] !== undefined) 
                    && (item[key] !== value)) {
                filtered.push(item);
            }
        });
        return filtered;
    };
});

Then use it from any directive like this:

...| notEqual:'<keyName>':<valueToCompareAgainst>

E.g.:

app.directive("mytag", function() {
    return {
        restrict: "E",
        template: "<div ng-repeat=\"item in myModel | notEqual:'a':null\">"
                + "    item: {{item}}"
                + "</div>",
        scope: {
            myModel: "="
        }
    };
});

See, also, this other other short demo.


UPDATE

It might be a better idea to use a service or a factory for utility methods that should be available to many controllers/scopes and should be customizable. E.g.:

app.factory("notNullFactory", function() {
    var factory = {};
    factory.notNull = function(caption) {
        return function(item) {
            console.log(caption + " " + JSON.stringify(item));
            return (item !== null);
        };
    };
    return factory;
});

Now, you can use notNullFactory's notNull(...) function to create customizable filter-functions:

app.directive("mytag", function(notNullFactory) {
    return {
        restrict: "E",
        template: "<div>"
                + "    <div ng-repeat=\"item in myModel | filter:notNull('Checking')\">"
                + "        item: {{item}}"
                + "    </div>"
                + "</div>",
        scope: {
            myModel: "="
        },
        link: function($scope) {
            $scope.notNull = function(caption) {
                return notNullFactory.notNull(caption);
            };
        }
    };
});

See, also, this other short demo.


It is not that your filter isn't called, rather it is not defined. At the time you define $scope.notNull, setting it equal to $rootScope.notNull, the latter is undefined.

Instead, you could get rid of the link property and use:

...| filter:$parent.notNull()...

See, also, this short demo.

Sign up to request clarification or add additional context in comments.

6 Comments

this will work assuming that the parent is rootScope. My tag can be nested in other controllers .How can i do this ? If I am not mistaken for ng-click it knows how to resolve the method also from a parent scope
This is exactly what I tried to avoid . This will be a general purpose function and I want it to be usable from within any directive with any usage of filters. But I think it is also important , how I got here.I basically wanted to filter all non null elements (so no extra function). This " ...| filter:{myProp:!null}" didn't cut it ,it worked for all values except null. Can I make the default expression({myProp:!null}) work ?
@OvidiuBuligan: Sorry, but I really don't understand what should be a general purpose function and why a factory is not reusable from within any directive. Could you, please, elaborate ?
I want to be able to create more directives and be able to use the notNull comparator in any filter without needing to add it to the directive's scope. An alternative wouldn't even need a function and be ...| filter:{myProp:!null} but this doesn't work and I don't know why
@OvidiuBuligan: Take a look at my (yet again) updated answer. Let's hope this time it is what you've been looking for :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.