6

I am new to AngularJS and would like to create functionality for a login page similar to what you find here when you click the 'Forgot Password' link:

http://bootsnipp.com/snippets/featured/login-amp-password-reminder#comments

Is it best to use a directive, since this is behavioral, instead of a controller? I've tried quite a bit with creating a controller for it, but as I search for help on the subject I find that using a controller for this may not be the way to go. Here was my latest trials which was unsuccessful (the link does nothing when clicked):

on controller side in a js file:

angular.module('mean.users')
    .controller('SwitcherCtrl', ['$document',
        function($document) {
        $document.ready(function () {
            $document.getElementById('olvidado').click(function (e) {
                e.preventDefault();
                $document.getElementById('form-olvidado').toggle('500');
            });
            $document.getElementById('acceso').click(function (e) {
                e.preventDefault();
                $document.getElementById('form-olvidado').toggle('500');
            });
        });
    }
])

on html side, I included ng-controller="SwitcherCtrl" where necessary.

codenaugh
  • 857
  • 2
  • 12
  • 27

3 Answers3

8

JQuery approach is completely incompatible with AngularJS. DOM Manipulation is only allowed in directives in the link function otherwise it is a very bad practice. Try to start from scratch and forget about JQuery. The magic of AngularJS happens with 2-way bindings.

You could use a directive, with a login controller and a factory/service to hold the username and password and send it to the database. For this login there is definitely no need for JQuery at all. You can check this question here: AngularJS- Login and Authentication in each route and controller

edit: In your question above, it is not a directive instead of a controller. A directive can have a controller that is applied to a specific scope. You could do the same thing with both but depends how many times you will reuse this login snippet - I guess you won't need it but I believe it is still good practice to make one.

edit 2: if you havent' read this one, please do it! I believe you will answer most of your questions about the two different (opposite I would say) technologies. "Thinking in AngularJS" if I have a jQuery background? Also since I came from Jquery background too, I followed these four resources in order and now I can make most of the things I want:

edit 3: Since I saw good interest in my answer I decided to expand it with what to avoid/best practices so the code is more testable, maintainable and easier to migrate to Angular 2:

Community
  • 1
  • 1
Michail Michailidis
  • 11,792
  • 6
  • 63
  • 106
  • The jQuery and javascript is being used to make the screen change from 'access account' to 'forgot password' when the link is clicked. My question relates to that exact functionality that you see in the link I provided. The authentication is separate from my question and is already in works. I have just been stuck on making the behavior, which I find very neat, that you see in the link I provided. – codenaugh Oct 15 '14 at 21:00
  • Yeah ignore the Authentication and try to rebuild the login in the way that this link has done it. You should not have any behavior and any DOM manipulation in the controller as you currently do. The controller should also not have any state that's why you need a factory/service to hold the username and password for it. The controller just sends the data through the repository to the server. The example doesn't show this one but it is a good step towards Angular way of building things and not JQuery. – Michail Michailidis Oct 15 '14 at 23:16
  • Right, after trying to solve my issue by searching google, I had read that it may belong in a directive instead of a controller. I want to know how to get the exact same behavior as the jQuery script, but using Angular. I understand some basics of how it is structured, but I could not figure out what code needed to be in the directive. Your answer seems more geared toward the login page, as a whole, which is why I have not selected it as the answer. I fear the other answer, using active and !active, may be a jerry-rigged way of simulating the visual effect, instead of actually reproducing it. – codenaugh Oct 16 '14 at 01:36
  • I will try to recreate it from scratch tomorrow if I have time :) – Michail Michailidis Oct 16 '14 at 02:17
  • Don't worry about it. I found it! Thanks for your assistance. – codenaugh Oct 16 '14 at 04:27
  • Ok! if you made it then please post the code for others to see :) – Michail Michailidis Oct 16 '14 at 04:33
  • I did, but couldn't accept as answer for 24 hours ;) – codenaugh Oct 17 '14 at 06:13
  • @clanier9 I added some resources in my last edits - this way you can understand how angularjs doesn't work and learn with incremental examples as I did when I came with jquery background ;) – Michail Michailidis Oct 27 '14 at 16:22
  • 1
    I appreciate it. The shaping up with angular from codeschool was very helpful and the egghead.io tutorial videos are a great way to learn with more examples. Thanks! – codenaugh Oct 28 '14 at 17:45
3

You can try this out, it uses directives and html. Whether the login or forgot username shows is tied to the state of a scope variable in the directives link function.

Fiddle

<div ng-app="myApp">

    <div my-auth>

        <div ng-show="active">
            <form name="login">
                <input type="email" ng-model="email" placeholder="your@email.com" required />
                <input type="password" ng-model="passwd" required />
                <button ng-disabled="!login.$valid">Login</button>
            </form>
            <a href="#" ng-click="toggle()">forgot password?</a>
        </div>

        <div ng-show="!active">
            <form name="forgot">
                <input type="email" ng-model="email" placeholder="your@email.com" required />
                <button ng-disabled="!forgot.$valid">Reset Password</button>
            </form>
            <a href="#" ng-click="toggle()">access</a>
        </div>
    </div>
</div> 

The directive

angular.module('myApp', [])
.directive('myAuth', function(){
    return {
        link: function(scope, elem, attr){
           scope.active = true;
           scope.toggle = function(){
               scope.active = !scope.active;
           };
        }
    };
});
Gabs00
  • 1,869
  • 1
  • 13
  • 12
1

Thanks to everyone who answered. They kicked off this thing moving in the right direction and I was able to improve upon it to come to the exact answer shown below.

The HTML:

<div ng-controller="SwitcherCtrl">
    <div data-fold-toggle="active">
        <form id="login">
            <input type="email" ng-model="email" required="">
            <input type="password" ng-model="password" required="">
            <button type="submit">Login</button>
            <a ng-click="active=!active">Forgot your password?</a>
        </form>
    </div>
    <div data-fold-toggle="active" style="display: none;">
        <form id="forgotpw">
            <input type="email" ng-model="email" required="">
            <button type="submit">Reset Password</button>
            <a ng-click="active=!active">Account Access</a>
        </form>
    </div>
</div>

The Controller & Directive:

.controller('SwitcherCtrl', function($scope) {
    $scope.active = true;
})
.directive('foldToggle', function() {
    return {
        restrict: 'A',
        scope:{
            isOpen: '=foldToggle'
        },
        link: function(scope, element) {

            scope.$watch('isOpen', function(newVal,oldVal){
                if(newVal !== oldVal){
                    element.toggle(200);
                }
            });
        }
    };
});
codenaugh
  • 857
  • 2
  • 12
  • 27