1

I'm filtering a list of objects in AngularJS using ng-repeat:

<tr ng-repeat="application in page.applications | filter: {DisplayName:page.ApplicationSearchValue}">
    {{application.DisplayName}}
</tr>

If the user puts an exclamation point as the first character in the search box, then Angular interprets that as a negation symbol. So !MyApplication returns all the applications except for MyAppliction.

I tried using a custom function as description in the Angular documentation for filter, but the exclamation point never finds its way into the function.

I found that the code is going through the following function in the AngularJS source code, which is basically enforcing that the exclamation point gets special treatment:

function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
  var actualType = getTypeForFilter(actual);
  var expectedType = getTypeForFilter(expected);

  if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
    return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);

      .....

My current "solution" is to change the filter object to:

filter: {DisplayName:(page.ApplicationSearchValue.indexOf('!') == 0 ? page.ApplicationSearchValue.substring(1) : page.ApplicationSearchValue)}

But it's only a matter of time until QA figures out that the problem would still occur if someone started the search box with !!.

Is there a common pattern for dealing with this situation?

HaveSpacesuit
  • 3,572
  • 6
  • 40
  • 59
  • Show us how you tried using a custom function. – JB Nizet Dec 05 '16 at 17:02
  • `ctrl.filterFunc = function(actual, expected) { expected = expected.indexOf('!') == 0 ? expected.substring(1) : expected; return actual.toLowerCase().indexOf(expected) != -1; }` But the value of expected never included the exclamation point. – HaveSpacesuit Dec 05 '16 at 17:07
  • Don't pass a comparator. Pass a function as the unique argument of the filter. Make this function return true if the element should be accepted by the filter, and false otherwise. – JB Nizet Dec 05 '16 at 17:10

1 Answers1

1

I ended up using a directive I modified from this post. https://stackoverflow.com/a/15346236/2908576

MyApp.directive("noNegation", [function() {
    return {
        require: "ngModel",
        link: function(scope, element, attrs, ngModelController) {
            ngModelController.$parsers.push(function(data) {
                while (data.indexOf("!") == 0)
                    data = data.substring(1);
                return data;
            });
        }
    };
}]);

It ignores all exclamation points at the beginning of the input. That means that a search for !!!MyApplication still returns MyApplication, even though the exclamation points aren't in the name.

Community
  • 1
  • 1
HaveSpacesuit
  • 3,572
  • 6
  • 40
  • 59