1

I am creating a forgot password function for an application I am building and so I built a function that sends an $http request to a PHP resource that sends the user a reset email. When the request resolves than I display a twitter bootstrp modal using an angular directive that tells the user if their email was successfully sent or not.

The issue I am having is that the scope of the controller and the directive seem different as updating the feedback in my controller does not update the output of the directive.

My controller:

  angular
        .module('enigma.auth')
        .controller('Auth', Auth);

  Auth.$inject = ['authFactory'];

  function Auth(authFactory) {
        var auth = this;
        auth.forgotPassword = forgotPassword;
        auth.forgotPasswordFeedback = '';

        function forgotPassword(email) {
              if(email) {
                    authFactory.forgotPassword({ email: email })
                          .then(function(res) {
                                auth.forgotPasswordFeedback = res.message; // auth.forgotPasswordFeedback is set to the correct value now, however this isn't reflected in the directive.
                                $('#forgotPassword').modal();
                          });
              }
        };
  }

My directive:

  angular
        .module('enigma.forgotPasswordDirective', [])    
        .directive('forgotPasswordDirective', forgotPasswordDirective);

  function forgotPasswordDirective() {
        return {      
              bindToController: true, // I thought this told the directive to use the controllers scope instead of an isolated scope...
              controller: 'Auth',
              controllerAs: 'auth',
              templateUrl: 'modules/auth/forgotPassword.html'
        }
    }

The template:

<div class='modal fade' id='forgotPassword'>
    <div class='modal-dialog'>
        <div class='modal-content'>
            <button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button>
            <div class='row'>
                <div class='col-xs-12'>
                    <h3>Password Recovery</h3>
                    <p>
                        {{auth.forgotPasswordFeedback}} <!-- this value is never updated :( -->
                    </p>
                    <p>
                        <button class='btn btn-primary'  data-dismiss='modal'>Close</button>
                    </p>
                </div>
            </div>
        </div>
    </div>
</div>

Lastly I have this all included inside my registration template which is bound to the registration controller (Note: Don't the forgot password directive is bound to the auth controller), here's the relevant bits.

<div class='form-group'>
    <label for='email'>Email:</label>
    <input class='form-control' name='email' ng-model='reg.user.email' required type='email' ng-blur='reg.alreadyRegistered()' />
    <div ng-messages='reg.regForm.email.$error' ng-if='reg.regForm.email.$dirty'>                       
        <div class='error' ng-message='userExists'>This user already exists. <a href='#' ng-click='auth.forgotPassword(reg.user.email)' title='Forgot password' ng-controller='Auth as auth'>Forgot password?</a></div>
    </div>
</div>
...
<forgot-password-directive></forgot-password-directive>
5
  • which version of angular are you using currently? bindToController changed in 1.4 Commented Dec 1, 2015 at 18:21
  • Why do you want separate modules for the directive and controller? Commented Dec 1, 2015 at 18:33
  • Because forgot password needs to be used in multiple controllers. Authentication Ctrl uses it for login and Registration Ctrl uses it during registration. Commented Dec 1, 2015 at 18:36
  • I think you still need to define which variables you need in your scope, OR use the new 1.4 bindToController methodology. If you change bindtoController to {forgotPasswordFeedback: '='} does it do the two-way binding you expect? Commented Dec 1, 2015 at 18:37
  • No there is no change when using bindToController: { forgotPasswordFeedback: '=' } Commented Dec 1, 2015 at 18:40

1 Answer 1

1

It works, for example, if you wrap the directive inside the controller:

<div ng-controller='Auth as auth'>
    <div class='form-group'>
        ...
        <a href='#' ng-click='auth.forgotPassword(reg.user.email)' title='Forgot password'>Forgot password?</a>
    </div>
    <forgot-password-directive></forgot-password-directive>
</div>

However, in addition, I would use a simpler approach and define the directive followingly:

function forgotPasswordDirective() {
    return {      
        scope: false,
        templateUrl: 'modules/auth/forgotPassword.html'
    }
}

If you are familiar with Node, you may clone and run the example from here: https://github.com/masa67/NgBind.

Sign up to request clarification or add additional context in comments.

2 Comments

This is what I had already done. I don't really like needing to place the directive inside the form next to the element but it works. Also there is no need to define scope in the directive at all, just templateUrl is needed.
I have no idea why your original code is not working. Updating auth.forgotPasswordFeedback in forgotPassword() does not get reflected in the directive. I just tested that it has nothing to do with the promise nor the modal. I also updated auth.forgotPasswordFeedback inside Auth in $timeout(), and those updates were reflected in the directive correctly. It seems that the event handling is here the issue.

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.