John Dorean
John Dorean

Reputation: 3874

Angular not updating input value based on model value

My Angular application has two routes that use the same controller and partials. The controller and partials behave in very slightly different ways based on the route used, hence why they both share the same code. These are the routes:

$routeProvider.when('/join', {templateUrl: '/partials/global-shared/join.html', controller: HouseJoinController});
$routeProvider.when('/join/:code', {templateUrl: '/partials/global-shared/join.html', controller: HouseJoinController});

Then, in the controller, I'm checking if a code is supplied and making an API call and updating a model based on the result from the API:

if ($routeParams.code) {
    API.post('signUp', 'invitedClient', 'getTenantDetails', {code: $routeParams.code}, function(result) {
        $scope.firstName = result.client.firstName;
    });
}

Finally, my partial has an input element which is bound to $scope.firstName using ng-model:

<input type="text" name="firstName" ng-model="firstName" ng-pattern="/^[a-zA-Z-']+[ ]?[a-zA-Z-']+$/" required>

When I load the page with a code supplied, I can see the API call and the results it's returning in Chrome's developer tools, and I've verified that $scope.firstName is being updated with the result from the API by console.log()ing it.

However, it's not getting updated in the input element. What's even weirder, is that if I do {{ firstName }} right before the input element, I can see the correct firstName model being output.

So the model is being updated, and Angular knows it';s new value because it can print it to the page, but it's not updating the input value.

I've also tried using $scope.$apply() in the API callback function, like so:

if ($routeParams.code) {
    API.post('signUp', 'invitedClient', 'getTenantDetails', {code: $routeParams.code}, function(result) {
        $scope.$apply(function() {
            $scope.firstName = result.client.firstName;
        });
    });
}

But Angular throws an error saying: Error: [$rootScope:inprog].

Upvotes: 0

Views: 381

Answers (2)

Michael Vashchinsky
Michael Vashchinsky

Reputation: 2137

What is API?

If you use something other than Angular's $http service, Angular has no way to know that your model was asynchronously updated.

So you probably wonn't need $apply() if you

  • use $http service
  • use $q in your API.post method to resolve/reject the response.

Also you can try to write your $apply like this (according to the docs, scope is passed into the function):

$scope.$apply(function(scope) {
  scope.firstName = result.client.firstName;
});

And, as was mentioned, the best practice is to use instance objects on $scope and not primitives to avoid $scope inheritance issues:

$scope.client = receivedClient;

and

ng-model="client.firstName"

where needed

Upvotes: 0

wilver
wilver

Reputation: 2116

I think it's a problem related to javascript prototypal inheritance. I suggest you to use an object in the $scope that contains your property. Read this documentation for better explanation. You can read this:

This issue with primitives can be easily avoided by following the "best practice" of always have a '.' in your ng-models – watch 3 minutes worth. Misko demonstrates the primitive binding issue with ng-switch.

Having a '.' in your models will ensure that prototypal inheritance is in play. So, use
<input type="text" ng-model="someObj.prop1"> rather than
<input type="text" ng-model="prop1">.

Upvotes: 0

Related Questions