admin管理员组

文章数量:1391995

I have an array of objects in scope, which I'm looping over with ng-repeat. I want to filter out some elements based on their values, but it seems like ng-if is pletely ignored.

I've set up this simple plunk to illustrate: .
Here's the controller:

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';

  $scope.events = [
    {key: "ClassName", value: "exception", age:12},
    {key: "Message", value: "oops", age: 25},
    {key: "Stack", value: null, age: 35}
    ]
});

And the HTML template:

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="[email protected]" src=".0.8/angular.min.js" data-semver="1.0.8"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <p>Hello {{name}}!</p>
    <ul>
      <li ng-repeat="event in events" ng-if="event.age > 20">
        [{{$index + 1}}] {{event.key}}: {{event.value}} - {{event.age}}
      </li>
    </ul>
  </body>

</html>

The ng-if directive is supposed to filter out the first element of the array, bit it is displayed anyway. What have I missed that ignores the ng-if?

I have an array of objects in scope, which I'm looping over with ng-repeat. I want to filter out some elements based on their values, but it seems like ng-if is pletely ignored.

I've set up this simple plunk to illustrate: http://plnkr.co/edit/Aj0hpZQTfnkQ6BYG8DRb.
Here's the controller:

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';

  $scope.events = [
    {key: "ClassName", value: "exception", age:12},
    {key: "Message", value: "oops", age: 25},
    {key: "Stack", value: null, age: 35}
    ]
});

And the HTML template:

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="[email protected]" src="https://ajax.googleapis./ajax/libs/angularjs/1.0.8/angular.min.js" data-semver="1.0.8"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <p>Hello {{name}}!</p>
    <ul>
      <li ng-repeat="event in events" ng-if="event.age > 20">
        [{{$index + 1}}] {{event.key}}: {{event.value}} - {{event.age}}
      </li>
    </ul>
  </body>

</html>

The ng-if directive is supposed to filter out the first element of the array, bit it is displayed anyway. What have I missed that ignores the ng-if?

Share Improve this question asked Nov 12, 2013 at 8:35 AntoineAntoine 5,26512 gold badges56 silver badges88 bronze badges 1
  • "The ng-if directive is supposed to filter", no its not, it suppose to decide whether the whole element will be rendered or not, voted for CD.. – bresleveloper Commented Nov 12, 2013 at 8:50
Add a ment  | 

3 Answers 3

Reset to default 4

I suppose the right way would be using a filter, for example:

<li ng-repeat="event in events | filter:greaterThan">

Working example: http://plnkr.co/edit/Qy3BVEogEgGivtqel73b?p=preview

I've updated your Plunkr to solve your issue using the code below.

I frequently use two custom angular modules, FilterIncludeIf and UtilCompare to provide ng-if-like functionality to ng-repeats.

FilterIncludeIf has UtilCompare as a dependency and takes two arguments. The first is the parison operator in string form (">=" in your case).

The second is an Object. The keys should be set to the keys of the individual objects returned from the ng-repeat statement (customer in the example below) whose values you'd like to pare. The values should be set to the value you'd like to pare against.

Looking at example-snippet.html, includeIf ends up filtering customers.all and ensuring that the only customers that are rendered are ones where all of the following statements are true.

customer[firstname] != customers.all.current.data.firstname`
customer[lastname] != customers.all.current.data.lastname`
customer[email] != customers.all.current.data.email`

example-snippet.html

<li 
    ng-repeat="customer in customers.all | filter:query | includeIf : '!=' : {
        firstname   : customers.current.data.firstname, 
        lastname    : customers.current.data.lastname,
        email       : customers.current.data.email, 
    }" 
    class="tab"
    >
    <div class="info">
        <h4 class="subheader name">
            {{customer.firstname}}&nbsp;{{customer.lastname}}
        </h4>
        {{customer.email}}
    </div>
</li>

Filter - includeIf

angular
.module('FilterIncludeIf', [
    'UtilCompare'
])  
.filter('includeIf', function (pare) {
    return function (items, parator, attrs) {
        var filteredInput = [];

        for (var i = 0; i < items.length; i++) {
            var item = items[i],
                numOfAttrs = 0,
                numOfMatchedAttrs = 0;
            for (var key in attrs) {
                numOfAttrs++
                var value = attrs[key],
                    parison = pare
                        .these(item[key], value)
                        .by(parator)
                        .eval();

                if (parison) numOfMatchedAttrs++;
            }
            if (numOfAttrs == numOfMatchedAttrs) filteredInput.push(item);
        }

        return filteredInput
    };
});

Factory - pare

angular
.module('UtilCompare', [])
.factory('pare', function () {
    var _by = undefined,
        _a = undefined,
        _b = undefined;

    var parators = {
        '>'     : function(c, d) { return c > d },
        '<'     : function(c, d) { return c < d },
        '>='    : function(c, d) { return c >= d },
        '<='    : function(c, d) { return c <= d },
        '!='    : function(c, d) { return c != d },
        '!=='   : function(c, d) { return c !== d },
        '=='    : function(c, d) { return c == d },
        '==='   : function(c, d) { return c === d },
    }

    function by (parator) {
        _by = parator;
        return this
    }

    function these (a, b) {
        _a = a;
        _b = b;
        return this
    }

    function eval () {
        return parators[_by](_a, _b);
    }

    return {
        by     : by,
        these  : these,
        eval   : eval
    }

});

I think what you want is an actual filter.

Filters can be applied on expressions (like the repeat) and will return a list containing only items that fulfills the criteria of the filter. So in this case I think you would do.

  <li ng-repeat="event in events | maxAge:20">
    ...
  </li>

Note that maxAge is not one of the default filters (you can find them to the left in the here), you would have to create one on your own unless you can fit it into the existing ones. But creating filters is really easy, they are just functions that take an input, do whatever logic they feel like and then return the new values.

本文标签: javascriptAngular JS ngif not working within ngrepeatStack Overflow