0

I have a page with a couple of controllers and ng-includes. Before coming to actual problem i should give a little detail about my AngularJS app

It is on top of node and express It is communicating with passport running on express for authentication Now i wanted to have the same page for authenticated as well as unauthenticated users with some differences, lets say the first change was the profile option in nav bar -

ul.nav.navbar-nav.navbar-right(ng-show="identity.isAuthenticated()")

this unordered list has the options to be shown to authenticated users which works fine as soon as i login it is shown which means that the variables identity and the method is isAuthenticate are working fine But the problem is with the profile form which is a bootstrap modal box -

div.modal.fade(id="profileModal")
    div.modal-dialog
        div.modal-content
            div.modal-header
                button.close(data-dismiss="modal") ×
                h4 Update Profile
            div.modal-body
                form.form-horizontal(name="profileForm")
                    fieldset
                        .form-group
                            label.col-md-2.control-label(for="email") Email
                            .col-md-10
                                input.form-control(name="email", type="email", placeholder="Email", ng-model="email", required)
                        .form-group
                            label.col-md-2.control-label(for="fname") First Name
                            .col-md-10
                                input.form-control(name="fname", type="text", placeholder="First Name", ng-model="fname", required)
                        .form-group
                            label.col-md-2.control-label(for="lname") Last Name
                            .col-md-10
                                input.form-control(name="lname", type="text", placeholder="Last Name", ng-model="lname", required)
                        .form-group
                            label.col-md-2.control-label(for="password") Password
                            .col-md-10
                                input.form-control(name="password", type="password", placeholder="Password", ng-model="password")
                        .form-group
                            div.modal-footer
                                button.btn.btn-primary(ng-click="update()", ng-disabled="profileForm.$invalid") Submit
                                |  

                                a.btn.btn-default(data-dismiss="modal") Cancel

Now here i am using a different controller mvProfileCtrl which is as follows -

angular.module('app').controller('mvProfileCtrl', function($scope, mvAuth, mvIdentity, mvNotifier) {
    $scope.email = mvIdentity.currentUser.username;
    $scope.fname = mvIdentity.currentUser.firstName;
    $scope.lname = mvIdentity.currentUser.lastName;

    $scope.update = function() {
        var newUserData = {
            username: $scope.email,
            firstName: $scope.fname,
            lastName: $scope.lname
        }
        if($scope.password && $scope.password.length > 0) {
            newUserData.password = $scope.password;
        }

        mvAuth.updateCurrentUser(newUserData).then(function() {
            mvNotifier.notify('Your user account has been updated');
        }, function(reason) {
            mvNotifier.error(reason);
        })
    }
})

The problem here is as soon as i open the page and the user is not logged in the currentUser is empty object so it doesn't have anything inside it. So i get this error in console -

TypeError: Cannot read property 'username' of undefined
    at new <anonymous> (http://localhost:5000/app/account/mvProfileCtrl.js:2:42)
    at invoke (http://localhost:5000/vendor/angular/angular.js:3899:17)
    at Object.instantiate (http://localhost:5000/vendor/angular/angular.js:3910:23)
    at http://localhost:5000/vendor/angular/angular.js:7164:28
    at http://localhost:5000/vendor/angular/angular.js:6566:34
    at forEach (http://localhost:5000/vendor/angular/angular.js:327:20)
    at nodeLinkFn (http://localhost:5000/vendor/angular/angular.js:6553:11)
    at compositeLinkFn (http://localhost:5000/vendor/angular/angular.js:6007:15)
    at compositeLinkFn (http://localhost:5000/vendor/angular/angular.js:6014:13)
    at publicLinkFn (http://localhost:5000/vendor/angular/angular.js:5916:30) 

But as soon as i refresh the page the currentUser has all the required data and thats why there is no error. So, how do i make sure that when the user is authenticated then only bind the $scope variables to this controller or after that only start the controller.

The project source is a bit big thats why i did not include complete detail here, so if i missed out on any detail please suggest

Edit:: another possible bug after removing the mvIdentity and the currentUser part for debugging when i tried this -

angular.module('app').controller('mvProfileCtrl', function($scope, mvAuth, mvNotifier) {



    $scope.update = function() {
        console.log($scope.email);
        var newUserData = {
            username: $scope.email,
            firstName: $scope.fname,
            lastName: $scope.lname
        }
        if($scope.password && $scope.password.length > 0) {
            newUserData.password = $scope.password;
        }

        mvAuth.updateCurrentUser(newUserData).then(function() {
            $('#profileModal').modal('toggle');
            mvNotifier.notify('Your user account has been updated');
        }, function(reason) {
            mvNotifier.error(reason);
        })
    }
});

It gave me undefined , which suggests that my $scope is not bound to the profileForm object but if i use the watcher and then use the previous code suggested by then i find that the input elements indeed have the currentUsers firstname and lastname which tells that the $scope is attached there. I am not understanding what is going here, please can anyone explain a bit

i am applying the controller like this -

div(ng-include="'/partials/account/authNavBar'",ng-controller="mvProfileCtrl")

where authNavBar has this bootstrap modal code and the profileForm

1 Answer 1

1

Use the scope and watchers to your advantage. If you set mvIdentity on your scope with a reference to the service, you can add watchers and only update those properties when currentUser exists.

angular.module('app').controller('mvProfileCtrl', function($scope, mvAuth, mvIdentity, mvNotifier) {
    $scope.mvIdentity = mvIdentity;
    $scope.$watch('mvIdentity.currentUser', function(currentUser) {
        if (!currentUser) return;

        $scope.email = currentUser.username;
        $scope.fname = currentUser.firstName;
        $scope.lname = currentUser.lastName;
    });


    $scope.update = function() {
        var newUserData = {
            username: $scope.email,
            firstName: $scope.fname,
            lastName: $scope.lname
        }
        if($scope.password && $scope.password.length > 0) {
            newUserData.password = $scope.password;
        }

        mvAuth.updateCurrentUser(newUserData).then(function() {
            mvNotifier.notify('Your user account has been updated');
        }, function(reason) {
            mvNotifier.error(reason);
        })
    }
});
Sign up to request clarification or add additional context in comments.

2 Comments

oh, watchers were just the thing i needed, thanks a lot
Okay, one doubt does the watchers set the values of these variables as constants or after the find the mvIdentity.currentUser true they continuously set call this function, as when i tried to log the value of username from the update function it gave me the old value from mvIdentity.currentUser instead of the updated value from the form field.

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.