LoginSignup
0
0

More than 5 years have passed since last update.

[monaca]ui-routerでjson検索処理。

Last updated at Posted at 2017-09-25

jsonで一括取得ではなく、その都度検索したい、って場合の処理。

ベース

ui-routerでjsonを取得したリスト画面
[monaca]ui-routerでjson取得処理。

angular-animateの導入

詳細は、[monaca]ui-routerで詳細スワイプ処理参照。

animate.cssの導入

同上

html

index.html
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <meta http-equiv="Content-Security-Policy" content="default-src * data: gap: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
  <script src="components/loader.js"></script>
  <script src="script.js"></script>

  <link rel="stylesheet" href="components/loader.css">
  <link rel="stylesheet" href="css/style.css">
</head>
<body ng-app="MyApp">

    <ons-page>
        <!-- ツールバー -->
        <ons-toolbar>
            <div class="center">JSON検索</div>
        </ons-toolbar>

        <!-- 画面のメイン部分 -->
        <div>
            <ons-button ui-sref="search">JSON検索</ons-button>
        </div>

        <!-- 遷移読込部分 -->
        <div style="padding: 20px 10px;" ui-view></div>

        <!-- ローディング読込用ディレクティブ -->
        <my-loader></my-loader>

    </ons-page>

    <!-- リスト画面 -->
    <ons-template id="search.html">
        <div ng-controller="SearchController">
            <!-- 入力欄 -->
            <ons-input ng-model="searchText" modifier="underbar" placeholder="国名等" float></ons-input> 
            <!-- 検索ボタン -->
            <ons-button ng-click="searchCountry();">検索</ons-button>
            <div>{{message}}</div>
            <!--検索結果 -->
            <dl ng-repeat="(i, item) in list">
                <!-- 国名をタップしたら、詳細表示有無を反転させる -->
                <dt ng-click="shown[i] = !shown[i];">
                    <!-- 詳細未表示時は右向きアイコン -->
                    <ons-icon icon="fa-chevron-circle-right" ng-show="!shown[i]"></ons-icon>
                    <!-- 詳細表示時は右向きアイコン -->
                    <ons-icon icon="fa-chevron-circle-down" ng-show="shown[i]"></ons-icon>                              
                    {{item.country}}                    
                </dt>
                <!-- 詳細情報は、詳細表示ON/OFFの切り替えでCSSを設定し、アニメーション表示する -->
                <dd ng-show="shown[i]">
                    <ul>
                        <li>英語名:{{item.english}}</li>
                        <li>数: {{item.number}}</li>
                        <li>三字: {{item.three}}</li>
                        <li>二字: {{item.two}}</li>
                        <li>場所: {{item.place}}</li>
                        <li>各行政区分: {{item.division}}</li>
                    </ul>
                </dd>
            </dl>
        </div>
    </ons-template>

    <!-- ローディング画面 -->
    <ons-template id="loader.html">
        <div ng-if="$root.isLoading" class="loader-parent"><div class="loader">Loading...</div></div>
    </ons-template>
</body> 
</html>

json

country.json
{
    "list": [
        {
            "country": "アイスランド", 
            "division": "ISO 3166-2:IS", 
            "english": "Iceland", 
            "number": "352", 
            "place": "北ヨーロッパ", 
            "three": "ISL", 
            "two": "IS"
        }, 
        {
            "country": "アイルランド", 
            "division": "ISO 3166-2:IE", 
            "english": "Ireland", 
            "number": "372", 
            "place": "西ヨーロッパ", 
            "three": "IRL", 
            "two": "IE"
        }, 
(略)
    ]
}

引用元)国コード一覧CSV ISO 3166-1

javascript

script.js
var myApp = angular.module('MyApp', ['onsen', 'ui.router', 'ngAnimate']);

// 遷移処理
myApp.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {

        $stateProvider
            .state('search', {
                url: '/search',
                templateUrl: 'search.html'
            })

    }]);

// 検索画面用コントローラ
myApp.controller('SearchController', ['$scope', '$state', '$rootScope', 'JsonCountryService', function($scope, $state, $rootScope, JsonCountryService) {

        $scope.searchCountry = function() {
            // まず、ローディングを回す
            $rootScope.isLoading = true;

            // Jsonデータ取得
            JsonCountryService.run($scope.searchText).then(
                function(resultList) {
                    // 結果リストが取れたら、スコープに設定
                    $scope.message = resultList.length + "件見つかりました。";
                    $scope.list = resultList;

                    // ローディング終了
                    $rootScope.isLoading = false;
                }, function(response) {
                    $scope.message = "検索結果がありませんでした。";
                    $scope.list = null;

                    // ローディング終了
                    $rootScope.isLoading = false;
                }
            );
        }

    }]);

// ローディングタグ
myApp.directive('myLoader', function() {
        return {
            restrict : 'E',
            replace: true,
            templateUrl: "loader.html"
        };
    }); 


// 画面遷移タイミング処理
myApp.run(['$rootScope', '$transitions', '$state', function($rootScope, $transitions, $state){
    $transitions.onSuccess({to:'*'}, function(trans){
        // ページ読み込み成功

        // ローディングフラグOFF
        $rootScope.isLoading = false;
    });

}]);


// JSON読込サービス
myApp.service('JsonCountryService', ['$q', '$timeout', '$http', '$filter', function($q, $timeout, $http, $filter){
     this.run = function (searchText) {
        console.log("JsonCountryService searchText="+ searchText);

        var deferred = $q.defer();

        $timeout(function(){
            $http({
                method: 'GET',
                url: 'country.json'
            }).then(function successCallback(response) {    
                // 成功した場合           
                console.log("JsonCountryService success");

                var resultList;
                if (searchText && searchText.length > 0) {
                    // 検索文字列が指定されている場合、リストの中から該当値のものだけ取得する
                    // 検索範囲は絞りこまない
                    // 完全一致ではなく、部分一致とする
                    resultList = $filter("filter")(response.data.list, searchText, false);                  
                }
                else {
                    // 検索文字列が指定されていない場合、全データを返す
                    resultList = response.data.list;
                }

                // 検索結果を返す
                deferred.resolve(resultList);

            }, function errorCallback(response) {
                // 失敗した場合
                var msg = "JsonCountryService json取得失敗: "+ response.status;

                console.error(msg);
                console.log("response.data"+ response.data);
                console.log("response.headers"+ response.headers);
                console.log("response.config"+ response.config);
                console.log("response.statusText"+ response.statusText);
                console.log("response.xhrStatus"+ response.xhrStatus);

                deferred.reject(msg);
            });
        });

        return deferred.promise;
    };

}]);

css

style.css
/* --------------------- 検索結果 ------------------------------- */

dt {
    font-size: large;
    font-weight: bold;
}
ul {
    padding: 0px;
}


/* --------------------- 詳細項目の表示/非表示アニメーション ------------------------------- */

dd.ng-hide-remove {
    animation: bounceInLeft 0.5s ease 0s 1 normal;
    -webkit-animation: bounceInLeft 0.5s ease 0s 1 normal;
    display: block!important;
}

dd.ng-hide-add {
    animation: bounceOutLeft 0.5s ease 0s 1 normal;
    -webkit-animation: bounceOutLeft 0.5s ease 0s 1 normal;
    display: block!important;
}

()

処理の流れ

  1. JSON検索ボタン押下
    1. state=searchに遷移
  2. 検索ボタン押下
    1. searchCountryを実行
      1. $rootScope.isLoading = trueでローディングを表示する
      2. ローディングの詳細は[monaca]ui-router遷移時にローディング処理を入れてみた。参照。
      3. ng-model$scopeにバインドされたsearchTextを取得
      4. $scope.searchTextを引数に、JsonCountryServiceを実行
  3. JsonCountryService内部の処理
    1. country.jsonを取得
      1. 取得に成功した場合
        1. 検索文字列が指定されている場合
          1. $filter("filter")(response.data.list, searchText, false)
          2. 第一引数: 検索対象リスト
          3. 第二引数: 検索文字列(検索範囲を絞り込みたい場合は、{ "country": searchText }のように指定する
          4. 第三引数:false: 部分一致検索, (true: 完全一致検索)
          5. フィルタ結果を返す
        2. 検索文字列が指定されていない場合
          1. 検索結果全件を返す
      2. 取得に失敗した場合
        1. エラーメッセージを返す
  4. JsonCountryServiceから結果リストが戻ってきた場合
    1. 検索結果件数をmessageに設定
    2. 検索結果リストをlistに設定
    3. ローディング終了
  5. JsonCountryServiceから結果リストが戻ってこなかった場合
    1. エラーメッセージをmessageに設定
    2. ローディング終了
  6. ng-repeatで検索結果リストの内容をリスト表示する
    1. ddタグは、shown[i]がtrueの場合のみ表示する。(初期表示時、false)
    2. dtタグ押下時、shown[i]の値を反転する
      1. ddタグ表示のタイミングで、dd.ng-hide-removeスタイルクラスが実行され、bounceInLeftアニメーションが実施される
      2. ddタグ非表示のタイミングで、dd.ng-hide-addスタイルクラスが実行され、bounceOutLeftアニメーションが実施される
      3. アニメーションの詳細は、[monaca]ui-routerで詳細スワイプ処理参照。
    3. shown[i]=trueの場合、fa-chevron-circle-downアイコンを表示する
    4. shown[i]=falseの場合、fa-chevron-circle-rightアイコンを表示する

ソースコード

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