4

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);
});
4
  • Is the factory variable getting updated outside the controller ? Commented Apr 7, 2014 at 7:47
  • @ShidhinCr Yes I am updating it within the factory itself... Commented Apr 7, 2014 at 7:49
  • Do i have to apply $scope.watch if yes then almost in every controller I have to do that? which i think is not a good idea..as it is against DRY.. Commented Apr 7, 2014 at 7:52
  • I guess you might need to have a $watch. I have seen others also doing the same only Commented Apr 7, 2014 at 7:53

2 Answers 2

14

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`
});
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks that solved my part of problem....another problem is I am returning an empty model from backend and want to achieve the same
Sorry, I don't get this other problem with empty model.
This my another question with your example code(bit modified though) stackoverflow.com/questions/22911354/…
I'll take a look. Please, accept this answer if you think it solves the first problem.
This is absolutely correct. Thanks for the reminder. :)
|
7

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/

1 Comment

The first method works out for me pretty well. I'm new to AngularJs. This really helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.