Bashir Magomedov
Bashir Magomedov

Reputation: 2891

How to react in the view to changes in the controller

I understand that this maybe a very naïve question, however I haven’t been able to find a definite answer on the web so far.

The question is how do I react in the view to changes in the controller?

For example I wrote a login controller that uses a service to perform a request and should either let user in or inform him/her if the login attempt has failed:

 var loginFormControllerFunction = function($scope, $log, $location, authenticationService){
    $scope.errorMessage = "";

    $scope.submit = function() {
        $scope.errorMessage = "";
        $scope.loginSuccessful = false;
        authenticationService.authenticate($scope.credentials.userName, $scope.credentials.password).then(
            function(user) {
                var token = user.token;
                //TODO: Receive token. Keep this guy logged for sometime.
                $scope.loginSuccessful = true;
                //TODO 2: Navigate to the main page.
            },
            function(errorMessage) {
                $scope.errorMessage = errorMessage;
                //TODO 3: remove zis from here!!!!
                //alert (errorMessage);
            }
        );
    };
};

Based on how I understand the concept of separation of concerns and mv* pattern, at this stage the controller should not:

  1. directly perform any navigation from the page (at the line TODO 2)
  2. interact with UI in any fashion by popping up notifications etc (TODO 3).

In my understanding it should instead raise corresponding events (?)/ somehow inform whoever concerned about the result of the login operation. Then the view should navigate

  1. to the main page if the login attempt was successful
  2. or show a pop up otherwise

What am I missing? What is the best way to achieve this with angularjs?

Thanks.

Upvotes: 0

Views: 57

Answers (1)

Erik Honn
Erik Honn

Reputation: 7576

For part 1, I would redirect in the authenticationService instead. Or, if you want more control from the view, send a url as an argument when calling the submit method. The view itself cannot (easily) redirect you, that needs to be done in a service or controller by calling $location.path(myPath).

You are correct in that controller should not directly interact with the view in the way for example a Backbone or similar app would (i.e. modify the page with jQuery). What an Angular controller should do is to update the model, and it is up to the view if it wants to react to this model-change or not. Remember, Angular updates things in the view automatically when the model changes so you can use ng-show or other directives to show your message.

So in your controller you update $scope.errorMessage just as in your example, and in your view you do:

<form>
    ...
</form>
<span ng-show="errorMessage">Something went wrong: {{errorMessage}}</span>

The view will now display errorMessage as soon as it is set by the controller. Of course, the span here could be replaced with an arbitrary object like a modal popup or something else.

Upvotes: 2

Related Questions