Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditionally apply filters with ng-repeat

I have an object that contains a mixture of numbers and text for values. I'd like to apply the numbers filter to the object's value when it's a number (obviously). But when it isn't a number, I'd be okay with it just spitting out the string. As is, applying | number to the value formats the numbers, but leaves the string values empty (afterall, they aren't numbers).

I'm guessing it'll have to be a custom filter (which I have yet had a need to make). Is there a way to do it solely within the HTML when doing the ng-repeat?

<table>
      <tr ng-repeat="(metric, metricData) in data">
        <td>{{metric}}</td>
        <td>{{metricData | number}}</td>
      </tr>
</table>

$scope.data = { name:"this is the name", 
                score:48
                outcome:"as expected",
                attendance:820,
                total:212.34
              };
like image 275
EnigmaRM Avatar asked Jun 20 '13 05:06

EnigmaRM


People also ask

How do I filter in NG-repeat?

The ng-repeat values can be filtered according to the ng-model in AngularJS by using the value of the input field as an expression in a filter. We can set the ng-model directive on an input field to filter ng-repeat values.

Does ng-repeat create a new scope?

Directives that Create Scopes In most cases, directives and scopes interact but do not create new instances of scope. However, some directives, such as ng-controller and ng-repeat, create new child scopes and attach the child scope to the corresponding DOM element.

How do I get an index in NG-repeat?

Note: The $index variable is used to get the Index of the Row created by ng-repeat directive. Each row of the HTML Table consists of a Button which has been assigned ng-click directive. The $index variable is passed as parameter to the GetRowIndex function.

What does ng-repeat do?

Definition and Usage. The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object.


3 Answers

Here is the requested alternate version of the answer from @callmekatootie using ng-if (v1.1.5):

<table>
    <tr ng-repeat="(metric, metricData) in data">
        <td>{{metric}}</td>
        <td ng-if="isNumber(metricData)">{{metricData | number}}</td>
        <td ng-if="!isNumber(metricData)">{{metricData}}</td>
    </tr>
</table>

This has the advantage of only running the filter on the elements which are numeric. This is probably of little benefit in this case but may be useful in other more complex filter situations. To answer your other question about the built-in angular.isNumber, @callmekatootie does use that in the scope function isNumber, which is only a wrapper for using the built-in in the view.

Here is a fiddle

like image 160
Dan Avatar answered Oct 12 '22 23:10

Dan


You could try it this way - In your controller, you can have a function which identifies if the provided value is a string or a number:

$scope.isNumber = function (value) {
    return angular.isNumber(value);
};

Next, in your view you could have the following:

<table>
    <tr ng-repeat="(metric, metricData) in data">
        <td>{{metric}}</td>
        <td ng-show="isNumber(metricData)">{{metricData | number}}</td>
        <td ng-hide="isNumber(metricData)">{{metricData}}</td>
    </tr>
</table>

Thus, when the metricData is a number, it is filtered and when it is a string, it is output as it is.

like image 23
callmekatootie Avatar answered Oct 13 '22 00:10

callmekatootie


I know this is old, but I think the best solution is to move the logic to a filter.

app.filter("metricDataFilter", function($filter) {
    return function(value) {
      if(angular.isNumber(value)) {
          return $filter("number", value);  
      }

      return value;
    }  
}

That way the HTML is more concise, and angular won't have to redraw dom elements

<table>
    <tr ng-repeat="(metric, metricData) in data">
        <td>{{metric}}</td>
        <td>{{metricData | metricDataFilter}}</td>
    </tr>
</table>
like image 43
Matt Oakley Avatar answered Oct 13 '22 01:10

Matt Oakley