2017.1.15
2017.5.26

ローカルに保存したJSONファイルのインポート

ローカルマシンに保存してあるJSONファイルをfileコントールを使用してインポートを行う方法についてです。

本当はfileコントロールにng-changeを設定できたらいいのですが、残念ながらそれはできませんでした。

コード

HTML


<div ng-controller="SampleCtrl">
    <div>
        <button ng-click="selectFile()">ファイルのインポート</button>
        <input type="file" style="display:none" id="select-file" onchange="angular.element(this).scope().importSelectFile(this)" />
    </div>
    <p ng-bind="importStr"></p>
</div>

fileコントロールを使うと「ファイル選択」という変更できない文字列のボタンがユーザーに見えてしまうため、styleにdisplay:noneを設定して非表示にしています。代わりに置いたbuttonコントロールを経由してfileコントロールを利用します。

JavaScript


// コントローラー
myApp.controller('SampleCtrl', function ($scope, $timeout) {
    // ファイル選択
    $scope.selectFile = function(){
        angular.element(document.querySelector('#select-file')).click();
    };

    // インポート
    $scope.importSelectFile = function(evt){
        // 選択ファイルの読み込み
        var file = evt.files[0];
        var reader = new FileReader();
        reader.readAsText(file);
        reader.onload = function(){
            // 読み込んだデータをセット
            $scope.importStr = reader.result;
            if(isJson(reader.result)){
                // JSONに変換
                $scope.importData = angular.fromJson(reader.result);
            }else{
                alert("JSONデータではありません。");
            }
            // 画面リフレッシュ
            $timeout(function(){}, 100);
        };
        // fileコントロールの選択状態をリセット
        angular.element(document.querySelector('#select-file')).val(null);
    };

    // JSONデータの型チェック
    function isJson(arg){
        try{
            JSON.parse(arg);
            return true;
        }catch(e){
            return false;
        }
    }
});

reader.onload() 実行後に画面の状態が更新されないため、$timeout(function(){}, 100); を使って強制的に画面をリフレッシュしています。

fileコントロールの選択状態をリセットしている理由は、リセットしておかないと同じファイルが選択された場合にonchangeイベントが発生しないためです。

参考リンク

AngularJS】関連記事