5

コントローラー内に割り当てられるオブジェクトの配列が$scopeあり、部分テンプレート内の一連の div でフィルター処理されています。

  <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>

フィルターは別のfieldset要素に表示されます。

  <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>

2 つのフィルターを使用してモジュールをセットアップし、そのモジュールをアプリに渡します。

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;
    }
  });

このコードが機能することを懸念していますが、エラー コンソールを見ると、およびフィルターの for ループCannot read property 'length' of undefinedに関する多くのエラーが表示されます。これらのフィルターを if ステートメントでラップして、が定義されているかどうかを確認すると (たとえば、):filterNameentityTypeitemsfilterName

  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;
    }
  });

エラーを取り除き、同様に機能します。AngularJS が未定義itemの s をフィルターに渡すのはなぜですか? これらのフィルターが私の 2 つの s でのみ明示的に呼び出されている場合、これらのフィルターは他にどこで呼び出される可能性がありng-repeatますか?

4

2 に答える 2

15

フィルターを通過するデータがサーバーから非同期に取得されると想定しても安全ですか? ページが最初にレンダリングされ、angular がすべてを通過するとき、まだデータがないため、未定義です。データが戻ってきたら、再びダイジェスト サイクルを経て、今度はデータがあるので、すべて機能します。このため、フィルター関数の先頭にチェックを定義することをお勧めします。

于 2012-11-13T16:11:36.370 に答える
0

ページがレンダリングされると、Angular はすべてを調べます。初期段階でデータが空になる場合は、未定義のチェックを入れる必要があります。

      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;
    };
});
于 2016-07-12T19:00:49.597 に答える