Reputation: 1133
Hi I have got one question. I have got one object as following in my Factory
User: {
EmailAddress: ""
}
whenever i make http call I want to update that User.EmailAddress whith returned value. What is the best way of doing it in within the factory? so that at controller level I can just bind my $scope.Email to factory variable. This is what I am doing right now
GetLogOnModel: function () {
if ($location.path().indexOf("login") == 1) {
var promise = $http.get(config.headers.url + "LogOn").then(function (response) {
// The return value gets picked up by the then in the controller.
User.EmailAddress=response.data.Email;
return response.data
});
return promise;
// Return the promise to the controller
}
}
And in Controller
AccountFactory.GetLogOnModel().then(function (data) {
$scope.logOnModel = data;
}, function (err) {
console.log(err.reason);
alert(err.reason);
});
Upvotes: 4
Views: 14210
Reputation: 48211
Primitive types (such as strings) are not bound by reference. So you can't bind a scope property to EmailAddress
directly and expect it to get automatically updated.
Objects on the other hand are bound by reference, so you could do something like this:
app.factory('AccountFactory', function (...) {
...
var User = {
...
EmailAddress: null
};
function getLogOnModel() {
$http.get(...).then(function (response) {
User.EmailAddress = response.data.Email;
});
}
// Init model (or leave it for the controller to init it)
getLogOnModel();
return {
...
User: User,
getLogOnModel: getLogOnModel
};
});
app.controller('someCtrl', function (..., AccountFactory) {
$scope.user = AccountFactory.User;
// Now you can reference `$scope.user.EmailAddress`
// and it will be kept in sync with `AccountFactory.User.EmailAddress`
});
Upvotes: 14
Reputation: 10530
It should be pretty straight forward. Either you bind the instance of the service or just the email property to the $scope
.
Here I'm just updating the email after 5 secs.
myApp.factory('myService', function($http, $timeout) {
return {
email: '[email protected]',
updateEmail: function() {
var self = this;
$timeout(function() {
$http.get('/echo/json/').success(function() {
self.email = '[email protected]';
});
}, 5000);
}
};
});
1st Method: Bind the entire service on the scope as:
function MyCtrl($scope, myService) {
$scope.myService = myService;
myService.updateEmail();
});
<div ng-controller="MyCtrl">
myService: {{myService.email}}!
</div>
2nd Method
Just create a custom $watch
for email updates:
function MyCtrl($scope, myService) {
$scope.email = myService.email;
myService.updateEmail();
$scope.$watch(function() { return myService.email; }, function(newVal, oldVal) {
$scope.email = newVal;
});
}
<div ng-controller="MyCtrl">
$scope: {{email}}
</div>
I would recommend the first method because it requires only one $watch
to update the DOM i.e. for {{myService.email}}
whereas the second method requires two $watches
i.e. one to update the $scoped model ($scope.$watch
) and other to update the DOM as {{email}}
.
Demo: http://jsfiddle.net/HB7LU/3015/
Upvotes: 7