22738


お世話になります。Angularjsの勉強のため、本体価格から消費税額を表示するサンプルアプリを作りました。画面構成は、表示用のメイン画面と、消費税率などを変更する設定画面の2つです。しかし、設定画面からメイン画面に戻る際に、一部の機能に限り$scopeへの処理が画面に反映されない問題が発生しました。

＜問題詳細＞  
・設定画面には次の3つの機能があります  
(1)消費税率を使用するか否かのON/OFスイッチ  
(2)消費税率の値を入力するテキスト  
(3)設定を初期化するボタン  
→（3）のみボタンを押してもメイン画面に値が反映されない。  
おそらくng-modelでバインドされた(1)(2)と違い、(3)は内部処理ゆえの問題だと思うのですが、解決方法がわかりませんでした。

試してみたこととして、＄timeoutを使ってメイン画面で随時カウントアップする処理を追加しましたが、変わらず値は変更されませんでした。また、$scope.$apply()をメイン画面のコントローラー直下においてみましたが、見当違いの場所なのかこちらもうまくいきませんでした。

目標は(3)のボタンをクリック後、メイン画面に戻ると同時に値がバインドされることです。  
お力添えを頂ければ幸いです。

[code]

                    <!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:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
                    <script src="components/loader.js"></script>
                    <link rel="stylesheet" href="components/loader.css">
                    <link rel="stylesheet" href="css/style.css">
                    <script>
                        var app = ons.bootstrap();
    
                        // コントローラ間でデータを共有するサービス
                        app.factory('SharedStateService', function(){
                            var sharedData = {};
                            sharedData.data = {};
    
                            // データを設定
                            sharedData.set = function(data){
                              sharedData.data = data;
                              window.localStorage.setItem('Data', JSON.stringify(data));
                            };
    
                            // データを返す
                            sharedData.get = function(){
                                return sharedData.data;
                            };
                            return sharedData;
                        });
    
    
                        // メイン画面 Controller
                        app.controller('mainCtrl', function( $scope, SharedStateService, $timeout){      
    
                            //ページを更新するための処理          
                            $scope.testnum=0; 
                              $scope.updateValue = function(){
                                  $timeout(function(){
                                    $scope.testnum++;
                                    $scope.updateValue();
                                },1000);
                              }              
                            $scope.updateValue();
    
                //            $scope.$apply();
    
                            $scope.price = 0;//初期値                
                            var obj = JSON.parse(window.localStorage.getItem('Data'));
                            if (obj == null || Object.keys(obj).length == 0) {        
                                obj =　{taxMode:true, taxValue:0.8, taxMemo:"メモを入力"};
                            }
                            SharedStateService.set(obj)
                            $scope.Data = SharedStateService.get();  
                        }); 
    
                        // 設定画面 Controller
                        app.controller('settingCtrl', function( $scope, SharedStateService ){
    
                            $scope.Data = SharedStateService.get();     
    
                            $scope.saveStorage = function() {                
                                SharedStateService.set($scope.Data)
                            }
    
                            $scope.clear = function() {
                                $scope.Data =　{taxMode:true, taxValue:0.08, taxMemo:"メモを入力"};               
                                SharedStateService.set($scope.Data);
                                alert("初期化完了!");
                //                $scope.$apply();
                            }
                        });
                    </script>
                </head>
                <body>
                    <ons-navigator var="myNavigator" page="main.html">
                    </ons-navigator> 
    
                    <ons-template id="main.html">
                        <ons-page ng-controller="mainCtrl">
    
                            <ons-toolbar>
                                <div class="left"><ons-toolbar-button ng-click="myNavigator.pushPage('setting.html')"><ons-icon icon="fa-cog"></div>                
                                <div class="center">消費税額計算</div>
                            </ons-toolbar>
                            <div>ページ更新確認用{{testnum}} </div>                
    
                            <br />
                            <div style="text-align: center">
                                金額　
                                <input type="number" class="text-input" placeholder="税抜価格" ng-model="price"　>            
    
                                <span ng-show="Data.taxMode">
                                    <br/>
                                        ×
                                    <br/>
                                    消費税
                                    <input type="number" class="text-input" placeholder="消費税" ng-model="Data.taxValue">
                                    <br/>
                                    <br/>
                                    　={{price * Data.taxValue}}
                                </span>                　
    
                                <span ng-show="!Data.taxMode">
                                    <br/>
                                    <br/>
                                    ={{price}}                    
                                </span>  
                            </div>
    
                        </ons-page>
                    </ons-template>
    
                    <ons-template id="setting.html">
                        <ons-page ng-controller="settingCtrl">
                            <ons-toolbar>
                                <div class="left"><ons-back-button>Back</ons-back-button></div>
                                <div class="center">設定</div>
                            </ons-toolbar>
    
                            <div class="settings-header">消費税</div>            
                            <div style="text-align: center">
                                <ons-list modifier="inset" class="settings-list">
                                    <ons-list-item>
                                      消費税を使用する
                                      <ons-switch modifier="list-item" ng-model="Data.taxMode"  ng-checked="Data.taxMode" ng-change="saveStorage()"></ons-switch>
                                    </ons-list-item>
    
                                    <ons-list-item ng-show="Data.taxMode"　>              
                                        <input type="number" class="text-input" placeholder="消費税を小数点入力" 
                                        ng-model="Data.taxValue" ng-blur="saveStorage()" style="margin-top:5px;">    
                                    </ons-list-item>
                                </ons-list>
                                <br/>
                                <ons-button ng-click="clear()" >設定を初期化</ons-button>
                            </div>
                        </ons-page>
                    </ons-template>
                </body>
    
                <style>
                .settings-header {
                  font-weight: 500;
                  font-size: 14px;
                  opacity: 0.4;
                  padding: 10px 0 0px 10px;
                  margin-bottom: -4px;
                }
    
                .settings-list {
                  margin-top: 10px;
                }
                </style>
                </html>
    
[/code]


CC BY-SA 3.0
2016-03-02T09:56:04.890
22731
2016-03-02T13:33:06.547
14390
question
monaca html angularjs
Angularjsでページ遷移時にデータがバインドされない（localstorage利用）


コントローラ`mainCtrl`で定義した変数`obj`がサービス`SharedStateService`の`sharedData.data`に参照渡しされ、`sharedData.get()`はその参照渡しされた`obj`を返します。  
つまり、コントローラ`mainCtrl`および`settingCtrl`の

[code]

    $scope.Data = SharedStateService.get();
    
[/code]

は、`obj`が渡されることになります。  
(1)(2)は、`obj`を直接変更しているので動作しますが、(3)は、

[code]

    $scope.Data = {taxMode:true, taxValue:0.08, taxMemo:"メモを入力"};               
    SharedStateService.set($scope.Data);
    
[/code]

の処理で書き換えた`$scope.Data`がサービス`SharedStateService`の`sharedData.data`に参照渡しされるため、(1)(2)の動きが継続できなくなります。

回避方法はいろいろありますが、一つの例として、`angular.copy()`を使用してオブジェクトのコピーを行い、`setting.html`から`main.html`に戻る際に最新の状態を取得します。

私も最初のころは、オブジェクトの参照渡しには何度も悩まされ大変でした。

[code]

    var app = ons.bootstrap();
    
    // コントローラ間でデータを共有するサービス
    app.factory('SharedStateService', function() {
        var sharedData = {};
        sharedData.data = {};
    
        // データを設定
        sharedData.set = function(data) {
            sharedData.data = angular.copy(data);
            window.localStorage.setItem('Data', JSON.stringify(data));
        };
    
        // データを返す
        sharedData.get = function() {
            return angular.copy(sharedData.data);
        };
        return sharedData;
    });
    
    // メイン画面 Controller
    app.controller('mainCtrl', function($scope, SharedStateService, $timeout) {
        $scope.price = 0; //初期値
        $scope.Data = JSON.parse(window.localStorage.getItem('Data'));
        if ($scope.Data == null || Object.keys($scope.Data).length == 0) {
            $scope.Data = {
                taxMode: true,
                taxValue: 0.8,
                taxMemo: "メモを入力"
            };
            SharedStateService.set($scope.Data)
        }
        ons.ready(function() {
            myNavigator.on("prepop", function(e) {
                if (e.leavePage.name == "setting.html") {
                    $scope.Data = SharedStateService.get();
                }
            });
        });
    });
    
    // 設定画面 Controller
    app.controller('settingCtrl', function($scope, SharedStateService) {
        $scope.Data = SharedStateService.get();
        $scope.saveStorage = function() {
            SharedStateService.set($scope.Data)
        }
        $scope.clear = function() {
            $scope.Data = {
                taxMode: true,
                taxValue: 0.08,
                taxMemo: "メモを入力"
            };
            SharedStateService.set($scope.Data);
            alert("初期化完了!");
        }
    });
    
[/code]


CC BY-SA 3.0
2016-03-02T13:33:06.547
22738
2016-03-02T13:33:06.547
9566
22731
answer