LoginSignup
24
29

More than 5 years have passed since last update.

AngularJSのFilterでAND検索を実装してみる

Last updated at Posted at 2014-08-06

AngularJSのFilterを自作して、 AND検索(スペース区切りで複数ワード検索) を実装してみる。

まず、既存のFilterを用いた絞り込みをつくる

Service

各種メソッドを実装する。
今回は、フィルタをかける対象データを作成する getData() を生成する。

service.js
/**
 * コンストラクタ
 */
function SearchService() {
}

/**
 * データを返す
 */
SearchService.prototype.getData = function () {
    return [
        {
            id: 1,
            name: "空条承太郎",
            kana: "クウジョウジョウタロウ",
            note: "オラオラ"
        },
        {
            id: 2,
            name: "東方仗助",
            kana: "ヒガシカタジョウスケ",
            note: "変な髪型"
        },
        {
            id: 3,
            name: "荒木飛呂彦",
            kana: "アラキヒロヒコ",
            note: "歳を取らない"
        },
        {
            id: 4,
            name: "虹村億泰",
            kana: "ニジムラオクヤス",
            note: "東方仗助が岸辺露伴を困らせた時わたしは焼身自殺します"
        },
        {
            id: 5,
            name: "岸辺露伴",
            kana: "キシベロハン",
            note: "岸部露伴は動かない"
        },
        {
            id: 6,
            name: "広瀬康一",
            kana: "ヒロセコウイチ",
            note: "エコーズ"
        }
    ];
};

Controller

htmlにデータを渡す機能を担う。

controller.js
function SearchController($scope, searchService) {
    $scope.users = searchService.getData();
}

moduleに登録

作成したServiceとControllerをmoduleに登録する。
moduleは、Webアプリケーションでいうインスタンス化やアプリケーションの起動などを行うMain部分。
moduleの第一引数には、後述のng-app属性に指定している文字列を指定する。

main.js
angular.module("SearchApp", [])
    .service("searchService", SearchService)
    .controller("searchController", SearchController);

データ表示部分

ng-appに任意のアプリケーション名を指定。
これをしていしないとangularアプリケーションは動かないので注意。

index.html(head)
// 忘れずに指定
<html ng-app="SearchApp">

// 関連ファイルを読み込む
 <script type="text/javascript" src="js/service/service.js"></script>
    <script type="text/javascript" src="js/controller/controller.js"></script>
    <script type="text/javascript" src="js/main.js"></script>
index.html(body)

// 文字入力部分
<input type="text" ng-model="keyword" placeholder="Keyword" />

// 表示部分
<div ng-controller="SearchController">

    <table class="data-table">
        <thead>
        <tr>
            <th>ID</th>
            <th>氏名</th>
            <th>フリガナ</th>
            <th>備考</th>
        </tr>
        </thead>
        <tbody>
        <tr ng-repeat="user in users | filter:keyword">
            <td>{{user.id}}</td>
            <td>{{user.name}}</td>
            <td>{{user.kana}}</td>
            <td>{{user.note}}</td>
        </tr>
        </tbody>
    </table>
<div>

ここまでのデモはこちら

AND検索をつくる

オブジェクト探索

入力された文字列を解析するメソッドを追加する。
オブジェクト内に指定したキーワードに一致するものがあるかどうか判定する。

service.js
/**
 * オブジェクト内の値がキーワードと部分一致するかどうか判定
 * @param obj 検索対象オブジェクト
 * @param keyword キーワード配列
 * @returns {boolean}
 */
SearchService.prototype.keywordJudge = function (obj, keyword) {
    var self = this;

    if (angular.isArray(obj)) {
        // 配列の場合
        // 格納されている要素を順番にチェックし、ひとつでも部分一致した場合trueを返す
        return obj.some(function (child) {
            return self.keywordJudge(child, keyword);
        });
    } else if (angular.isObject(obj)) {
        // オブジェクトの場合
        // 子要素を順番にチェックし、ひとつでも部分一致した場合trueを返す
        var properties = Object.getOwnPropertyNames(obj);
        return properties.some(function (property) {
            var child = obj[property];
            return self.keywordJudge(child, keyword);
        });
    } else if (obj != null) {
        // オブジェクト、配列以外で、値がある場合
        // 文字列に変換し、部分一致した場合trueを返す
        return angular.toJson(obj).search(keyword) != -1;
    }
    // nullまたはundefinedの場合
    return false;
};

CustomFilterをつくる

ANDSearchFilter.js
/**
 * AND検索用のFilter
 * @param searchService
 * @returns {Function} Filterをかけたデータの配列
 */
function ANDSearchFilter(searchService) {
    return function (list, searchQuery) {

        if (searchQuery) {
            // 全角スペースを半角スペースに置換
            var query = searchQuery.replace(/ /g, " ");
        }

        // 検索フォームに文字が入力されている場合
        if (query) {
            // 検索対象ワードの配列を作成
            var queryWordArray = query.split(" ");

            var filteredList = [];

            list.forEach(function (obj) {
                // 検索キーワードでオブジェクトそれぞれを探索
                var isMatch = !queryWordArray.some(function (keyword) {
                    return !searchService.keywordJudge(obj, keyword);
                });

                // 検索キーワードがAND一致した場合、一覧に表示する配列に格納
                if (isMatch) {
                    filteredList.push(obj);
                }
            });
            return filteredList;
        }
        return list;
    };
}

Filterを登録

作成したフィルタを登録。

index.html(head)
<script type="text/javascript" src="js/filter/andSearchFilter.js"></script>
main.js
angular.module("SearchApp", [])
    .service("searchService", SearchService)
    .filter("andSearchFilter", ANDSearchFilter)
    .controller("searchController", SearchController);

データ表示部分を修正

元々 filter としていた部分を andSearchFilter に置き換える。

index.html
<tr ng-repeat="user in users | andSearchFilter:keyword">

まとめ

24
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
29