AngularJSのフィルターで配列やオブジェクトを複数統合する方法

AngularJSのフィルターで配列やオブジェクトを統合する方法

フィルターで配列やオブジェクトを統合

AngularJSを使用しているとフィルターで配列やオブジェクトを統合したいことがある。(通常はapp.js側で統合したほうが良いが)

AngularJSにはあらかじめconcatフィルターみないなものがないため必要な場合は自分で作成するかライブラリなどを活用する必要がある。

フィルターの作り方

angular-filterにconcatフィルターが入っているので通常はこちらを使用すれば問題ない。
https://github.com/a8m/angular-filter#concat

concatフィルターのコードの中身

カスタムフィルターの引数でcollectionとjoinedを受け取り未定義であればそのまま返し、配列であればconcat関数で統合、オブジェクトであればtoArrayで配列に変換してから統合されるようになっている。

function toArray(object) {
  return isArray(object) ? object :
    Object.keys(object).map(function (key) {
      return object[key];
    });
}
app.filter('concat', [function () {
    return function (collection, joined) {
      if (isUndefined(joined)) {
        return collection;
      }
      if (isArray(collection)) {
        return (isObject(joined))
          ? collection.concat(toArray(joined))
          : collection.concat(joined);
      }
      if (isObject(collection)) {
        var array = toArray(collection);
        return (isObject(joined))
          ? array.concat(toArray(joined))
          : array.concat(joined);
      }
      return collection;
    };
  }
]);

HTML側のコード

| concat:【統合する配列またはオブジェクト】で統合。

<li ng-repeat="item in foo | concat:bar">{{item.name}}</li>

concatフィルターの問題点

このフィルターは配列またはオブジェクトを1つしか統合することができない。(引数が固定されているため)

複数の配列またはオブジェクトを統合したい場合はargumentsオブジェクトによる可変個引数でフィルターを作成する。

<li ng-repeat="item in foo | concatMulti:bar:hoge">{{item.name}}</li>
app.filter('concatMulti', [function () {
  return function (collection, joined) {
    if (isUndefined(joined)) {
      return collection;
    }
    var result = [];
    for (var i = 1; i < arguments.length; i++) {
      result = (isObject(arguments[i]))
        ? result.concat(toArray(arguments[i]))
        : result.concat(arguments[i]);
    }
    if (isArray(collection)) {
      return (isObject(result))
        ? collection.concat(toArray(result))
        : collection.concat(result);
    }
    if (isObject(collection)) {
      var array = toArray(collection);
      return (isObject(result))
        ? array.concat(toArray(result))
        : array.concat(result);
    }
    return collection;
  };
}]);

AngularJSのフィルターで配列やオブジェクトを複数統合するサンプル