Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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 abgular 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

share|improve this question

1 Answer 1

up vote 1 down vote accepted

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);
        })
    }
});
share|improve this answer
    
oh, watchers were just the thing i needed, thanks a lot –  deadman Jun 20 '14 at 17:40
    
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. –  deadman Jun 20 '14 at 17:49
    
can you please check the edit –  deadman Jun 20 '14 at 18:03

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.