最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AngularJS - custom filter errors due to undefined arrays and still filters properly? - Stack Overflow

programmeradmin11浏览0评论

I have an array of objects getting assigned to $scope within a controller, and is being filtered in a series of divs within a partial template:

  <div class="entity-list">
    <!-- Folders -->
    <div class="entity-listing folder" ng-repeat="child in folders | filterName:nameFilter | entityType:filterType | orderBy:orderProp:orderAscDesc">
      <!-- Some HTML -->
    </div>
    <!-- Files -->
    <div class="entity-listing document" ng-repeat="child in documents | filterName:nameFilter | entityType:filterType | orderBy:orderProp:orderAscDesc">
      <!-- Some HTML -->
    </div>
  </div>

The filters are displayed in a separate fieldset element:

  <fieldset id="filters">
    <legend>Filters</legend>
    <label for="filter-name">Name Contains:</label>
    <input id="filter-name" ng-model="nameFilter">
    <label for="filter-type">Show:</label>
    <select id="filter-type" ng-model="filterType">
      <!-- some options -->
    </select>
    <label for="sort-field">Sort By:</label>
    <select id="sort-field" ng-model="orderProp">
      <!-- some options -->
    </select>
    <select ng-model="orderAscDesc">
      <!-- some options -->
    </select>
  </fieldset>

I have a module set up with two filters, and pass that module on to my app:

angular.module('widget', ['filters']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/homefolder', {templateUrl: 'widget/partial/entity-list.html', controller: HomeFolderCtrl}).
      when('/folder/:uuid', {templateUrl: 'widget/partial/entity-list.html', controller: FolderCtrl}).
      otherwise({redirectTo: '/homefolder'});
  }]);
angular.module('filters', []).
  filter('entityType', function() {
    return function(items, type) {
      var returnArray = [];
      for (var i=0,ii=items.length;i<ii;i++) {
        if (type == "both") {
          returnArray.push(items[i]);
        } else if (items[i].type == type) {
          returnArray.push(items[i]);
        }
      }
      return returnArray;
    }
  }).
  filter('filterName', function() {
    return function(items, str) {
      var returnArray = [];
      if (str != '') {
        for (var i=0,ii=items.length;i<ii;i++) {
          if (items[i].name.indexOf(str) !== -1) {
            returnArray.push(items[i]);
          }
        }
      } else {
        returnArray = items;
      }
      return returnArray;
    }
  });

I'm concerned that this code works, yet when looking at the error console, I get a bunch of errors saying Cannot read property 'length' of undefined regarding the filterName and entityType filters' for loops. If I wrap those filter in an if statement to check if items is defined (take for example filterName):

  filter('filterName', function() {
    return function(items, str) {
      var returnArray = [];
      if (items) {
        if (str != '') {
          for (var i=0,ii=items.length;i<ii;i++) {
            if (items[i].name.indexOf(str) !== -1) {
              returnArray.push(items[i]);
            }
          }
        } else {
          returnArray = items;
        }
      }
      return returnArray;
    }
  });

It gets rid of the error and works as well. Why would AngularJS pass in undefined items to the filters? Where else could these filters be getting called if they are only explicitly getting called in my two ng-repeats?

I have an array of objects getting assigned to $scope within a controller, and is being filtered in a series of divs within a partial template:

  <div class="entity-list">
    <!-- Folders -->
    <div class="entity-listing folder" ng-repeat="child in folders | filterName:nameFilter | entityType:filterType | orderBy:orderProp:orderAscDesc">
      <!-- Some HTML -->
    </div>
    <!-- Files -->
    <div class="entity-listing document" ng-repeat="child in documents | filterName:nameFilter | entityType:filterType | orderBy:orderProp:orderAscDesc">
      <!-- Some HTML -->
    </div>
  </div>

The filters are displayed in a separate fieldset element:

  <fieldset id="filters">
    <legend>Filters</legend>
    <label for="filter-name">Name Contains:</label>
    <input id="filter-name" ng-model="nameFilter">
    <label for="filter-type">Show:</label>
    <select id="filter-type" ng-model="filterType">
      <!-- some options -->
    </select>
    <label for="sort-field">Sort By:</label>
    <select id="sort-field" ng-model="orderProp">
      <!-- some options -->
    </select>
    <select ng-model="orderAscDesc">
      <!-- some options -->
    </select>
  </fieldset>

I have a module set up with two filters, and pass that module on to my app:

angular.module('widget', ['filters']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/homefolder', {templateUrl: 'widget/partial/entity-list.html', controller: HomeFolderCtrl}).
      when('/folder/:uuid', {templateUrl: 'widget/partial/entity-list.html', controller: FolderCtrl}).
      otherwise({redirectTo: '/homefolder'});
  }]);
angular.module('filters', []).
  filter('entityType', function() {
    return function(items, type) {
      var returnArray = [];
      for (var i=0,ii=items.length;i<ii;i++) {
        if (type == "both") {
          returnArray.push(items[i]);
        } else if (items[i].type == type) {
          returnArray.push(items[i]);
        }
      }
      return returnArray;
    }
  }).
  filter('filterName', function() {
    return function(items, str) {
      var returnArray = [];
      if (str != '') {
        for (var i=0,ii=items.length;i<ii;i++) {
          if (items[i].name.indexOf(str) !== -1) {
            returnArray.push(items[i]);
          }
        }
      } else {
        returnArray = items;
      }
      return returnArray;
    }
  });

I'm concerned that this code works, yet when looking at the error console, I get a bunch of errors saying Cannot read property 'length' of undefined regarding the filterName and entityType filters' for loops. If I wrap those filter in an if statement to check if items is defined (take for example filterName):

  filter('filterName', function() {
    return function(items, str) {
      var returnArray = [];
      if (items) {
        if (str != '') {
          for (var i=0,ii=items.length;i<ii;i++) {
            if (items[i].name.indexOf(str) !== -1) {
              returnArray.push(items[i]);
            }
          }
        } else {
          returnArray = items;
        }
      }
      return returnArray;
    }
  });

It gets rid of the error and works as well. Why would AngularJS pass in undefined items to the filters? Where else could these filters be getting called if they are only explicitly getting called in my two ng-repeats?

Share Improve this question asked Nov 13, 2012 at 15:57 ScottScott 6,73610 gold badges41 silver badges48 bronze badges 1
  • because you may want to deal with undefined or null in your filters, it is a sensible design choice IMO (you can write a default filter that check null or undefined and replace with a provided value for exemple: yourArrayPromise | default: [] – Guillaume86 Commented Nov 13, 2012 at 17:07
Add a comment  | 

2 Answers 2

Reset to default 15

Is it safe to assume that the data going through your filters is retrieved from the server asynchronously? When the page first renders, and angular goes through everything, there is no data yet, so it is undefined. Once the data returns, it goes through the digest cycle again, and then there is data this time, so it all works. For this reason, it's a good idea to have the defined check at the beginning of the filter function.

When the page renders, Angular examines everything. if in initial stage data is coming empty , then you should put check for undefined.

      app.filter('greaterThenHundred', function () {
    return function (items) {

        if (items == undefined)
            items = [];
        var filtered = [];
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            if (item.Salary > 100) {
                filtered.push(item);
            }
        }
        return filtered;
    };
});
发布评论

评论列表(0)

  1. 暂无评论