フィルターで配列やオブジェクトを統合
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のフィルターで配列やオブジェクトを複数統合するサンプル