2017-01-17 1 views
0

私は現在のユーザーのイメージを表示する "nav"コントローラを備えたnavbarを持っています。しかし、ユーザーがプロフィール写真を更新した場合、ナビ画像を変更することができません。ナビゲーションコントローラ内の

'use strict'; 
angular.module('clientApp').factory('Account', function ($http, toastr) { 
    var currentUser = null; 
    function getUser(callback, user) { 
    console.log('get user user ', user) 
    // if the user has already been retrieved then do not do it again, just return the retrieved instance 
    if (currentUser !== null && currentUser !== user) { 
     callback(currentUser); 
    } 
    if (currentUser === null) { 
     // retrieve the currentUser and set it as a property on the service 
     $http.get('/api/me').then(function (res) { 
     // set the result to a field on the service 
     currentUser = res.data; 
     // call the callback with the retrieved user 
     callback(currentUser); 
     }); 
    } 
    } 

    //updates the currentUser variable 
    function updateProfile(profileData, callback) { 
    console.log('profile data ', profileData); 
    $http.put('/api/me', profileData).then(function (res) { 
     currentUser = res.data; 
     callback(currentUser); 
    }).catch(function (response) { 
     if (response.data.message.length) { 
     for (var i = 0; i < response.data.message.length; i++) { 
      toastr.error(response.data.message[i]); 
     } 
     } 
    }); 
    } 
    return { 
    getUser: getUser, 
    updateProfile: updateProfile 
    }; 
}); 

ウォッチャー::私は明らかにここで何かが混乱してい

$scope.user = {}; 

    //watches for currentUser changes in account service 
    $scope.$watch(Account.getUser(function(user){}, $scope.user), function (newValue, oldValue) { 
    console.log('user update watch', newValue) 
     $scope.user = newValue; 
    }); 

は、ここに私のサービスです。私は$ watchの情報を見ていますが、これは私が期待したようにうまくいきません。おそらく、Account.getUserは$ watchの値を比較するために何も返さないので、代わりにコールバックを使用するからです。

誰かが間違っているところを指摘できたら、

+2

@NoobSterところで、単にコールバックを使用していて、単に約束を利用しているのではないのですか? –

答えて

0

$watchを正しく使用していない人にとっては、いつでも呼び出し元に約束を返すことができるので、コールバック関数を渡す必要はありません。

NavCtrlcurrentUserの変更をリッスンします。この変更は、保持され、コントローラ間で共有されます(userService)。 MainCtrlは、サービスを呼び出してユーザーをフェッチする場所です(ログインなどを模倣しています)。

ユーザーが知られていない、または変更されていない場合は、$qを使用してサービスからのユーザー情報を返すか、更新する必要があるときに$httpを使用してユーザー情報を返すことができます。これらは両方とも約束を返す。

ここにHTML

<body> 
    <!-- nav bar --> 
    <div ng-controller="NavCtrl"> 
    Nav 
    <div ng-bind="user.name"></div>  
    </div> 
    <br> 

    <!-- content --> 
    <div ng-controller="MainCtrl"> 
    Main 
    <div ng-bind="'User cached: ' + !!isCached"></div> 
    <br> 
    <input type="button" ng-click="getUser()" value="Get"> 
    </div> 
</body> 

はJavaScript

angular.module('app', []) 

.controller('NavCtrl', function($scope, userService) { 
    var unwatch = $scope.$watch(function() { 
    return userService.currentUser; 
    }, function(user) { 
    $scope.user = user || { name: 'No user' }; 
    }); 

    $scope.$on('$destroy', unwatch); 
}) 

.controller('MainCtrl', function($scope, userService) { 
    $scope.getUser = function() { 
    var id = Math.floor((Math.random() * 10) + 1); // 1...10 
    userService.getUser(id).then(function(user) { 
     $scope.isCached = user.cached; 
    }); 
    }; 
}) 

.factory('userService', function($q, $http) { 
    var userService = { 
    currentUser: null, 
    getUser: function(id) { 
     if (userService.currentUser && userService.currentUser.id === id) { 
     userService.currentUser.cached = true; 
     return $q.when(userService.currentUser); 
     } else { 
     var url = 'https://jsonplaceholder.typicode.com/users/' + id; 
     return $http.get(url).then(function(response) { 
      userService.currentUser = response.data; 
      return userService.currentUser; 
     }) 
     } 
    } 
    }; 

    return userService; 
}); 

imgur


関連plunker https://plnkr.co/edit/DzfAtI

+0

ありがとう、Mikko。クイック質問。 $ destroyで$ watchを呼び出す利点は何ですか? – NoobSter

+1

スコープが破棄されたときにウォッチャー機能が正しく登録されていないことを確認します。私がAngularを信じる前に私は自動的にそれをやっていましたが、考えているように100%働いていないようです(メモリリーク)。 –

-1

$watchの代わりに$rootScopeを使用できます。

このようにして、どのコントローラからでも更新できます。

あなたがサービスでインスタンス変数を使用して、このような何かを行うことができ
0

、あなたはグローバル変数にcurrentUserに格納されているので、あなたは、update api後のサービスでcurrentUser変数を更新すると

、あなたが送ることができますそれはサービスの応答として。私はwatchまたはrootscopeのいずれかを使用せずにこれを行っている

、以下のコードを見つけてください、また、ここで

が@Mikkoからのコードに基づいてコードが

angular.module('app', []) 
 

 
.controller('NavCtrl', function($scope, userService) { 
 
    $scope.getUser = function() { 
 
    var id = Math.floor((Math.random() * 10) + 1); // 1...10 
 
    userService.getUser(id).then(function(user) { 
 
     console.log('user',user); 
 
     $scope.user = user; 
 
    }); 
 
    }; 
 

 
}) 
 

 
.controller('MainCtrl', function($scope, userService) { 
 
    
 
}) 
 

 
.factory('userService', function($q, $http) { 
 
    var userService = { 
 
    currentUser: null, 
 
    getUser: function(id) { 
 
     if (userService.currentUser && userService.currentUser.id === id) { 
 
     userService.currentUser.cached = true; 
 
     return $q.when(userService.currentUser); 
 
     } else { 
 
     var url = 'https://jsonplaceholder.typicode.com/users/' + id; 
 
     return $http.get(url).then(function(response) { 
 
      userService.currentUser = response.data; 
 
      console.log(userService.currentUser); 
 
      return userService.currentUser; 
 
     }) 
 
     } 
 
    } 
 
    }; 
 

 
    return userService; 
 
});
<!DOCTYPE html> 
 
<html ng-app="app"> 
 

 
    <head> 
 
    <script data-require="[email protected]" data-semver="1.6.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script> 
 
    <link rel="stylesheet" href="style.css" /> 
 
    <script src="script.js"></script> 
 
    </head> 
 

 
    <body> 
 
    <div ng-controller="NavCtrl"> 
 
     From navigation controller. 
 
     <br><br> 
 
     <input type="button" ng-click="getUser()" value="Get"> 
 
     <br><br> 
 
     User Details: 
 
     <br><br> 
 
     <div ng-bind="user"></div>  
 
     <br><br> 
 
     Name: 
 
     
 
     <div ng-bind="user.name"></div>  
 
    </div> 
 
    <br> 
 
    
 
    </body> 
 

 
</html>
、あるスニペットを実行します

Here is the working demo

+0

これはうまくいくかもしれませんが、ここでの主な問題は、ユーザー情報を変更して別のナビゲーションを最新の状態に保つことです。 –

+0

あなたを取得できませんでしたか?私のコードから、更新メソッドが呼び出されると直ちにコールバックでサービスからのインスタンス変数を使用してユーザオブジェクトを更新しているので、 'watch'も使用していません。そこではアプリケーションを高速化します。 – Sravan

+0

与えられた実装では、サービス変数が他のコントローラから変更されていてもナビゲーションコントローラがあなたに電話したいと思っていないと、 '$ scope.user'は更新されません。 'updateProfile'です。この解決策を検討するためのプランナーを追加してください。 –

関連する問題