JSFiddle - React, Tailwind, and code Playground

HTML

<p>AngularJS AND Search Filter</p>

<div ng-controller="SearchController">
    <input type="text" ng-model="keyword" placeholder="Keyword"/>

    <table class="data-table">
        <thead>
        <tr>
            <th>ID</th>
            <th>氏名</th>
            <th>フリガナ</th>
            <th>備考</th>
        </tr>
        </thead>
        <tbody>
        <tr ng-repeat="user in users | andSearchFilter:keyword">
            <td>{{user.id}}</td>
            <td>{{user.name}}</td>
            <td>{{user.kana}}</td>
            <td>{{user.note}}</td>
        </tr>
        </tbody>
    </table>
    <p>
        <small>※ サンプルデータは、
            <a href="http://ja.wikipedia.org/wiki/%E3%82%B8%E3%83%A7%E3%82%B8%E3%83%A7%E3%81%AE%E5%A5%87%E5%A6%99%E3%81%AA%E5%86%92%E9%99%BA">
                ジョジョの奇妙な冒険
            </a> から拝借しました
        </small>
    </p>
</div>

CSS

body {
    background-color: whitesmoke;
}

table, td, th {
    text-align: left;
    border: 1px solid;
}

th {
    background-color: darkgray;
}

td {
    background-color: lightgray;
}

JavaScript

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: "エコーズ"
        }
    ];
};

SearchService.prototype.keywordJudge = function (obj, keyword) {
    var self = this;

    if (angular.isArray(obj)) {
        // 配列の場合
        // 格納されている要素を順番にチェックし、ひとつでも部分一致した場合trueを返す
        return obj.every(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;
};

function ANDSearchFilter(searchService) {
    return function (list, searchQuery) {

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

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