Simple Ionic Login With AngularJS Last update: 2014-12-18

Simple Ionic Login With AngularJS

Many times you may want to have a login at the beginning of your app. Handling a login with Ionic and Angular is very straight forward. For the purpose of creating this Ionic Login Example, I will use a simple starting template from the Ionic guys und just add a login before the template app shows.

Complete example: How To Handle User Authentication With AngularJS Inside Your Ionic App

Setup the project

Go to your command line and start a new ionic app:

ionic start simple-login tabs
cd simple-login
ionic serve --lab

BTW: the —lab flag is quite new and shows how your app will look on ios & Android. Epic stuff the guys at ionic are creating!

Modify our template

As we want to display our login page before the tabs you see right now, we must add a new file in the www/templates folder, named login.html with this content:

<ion-view view-title="Login" name="login-view">
	<ion-content class="padding">
		<div class="list list-inset">
			<label class="item item-input">
				<input type="text" placeholder="Username" ng-model="data.username" />
			</label>
			<label class="item item-input">
				<input type="password" placeholder="Password" ng-model="data.password" />
			</label>
		</div>
		<button class="button button-block button-calm" ng-click="login()">Login</button>
	</ion-content>
</ion-view>

So here we have a simple view, a small login form and a button. We will assign everything needed in the controller later, for now lets add our route so we can see our view the first time. Therefore, open up the app.js and add this state to the already existing states:

  .state('login', {
      url: '/login',
      templateUrl: 'templates/login.html'
  })

You can run your app now, and you should see a view like this:

ionic-login1

If you want to make a login without credentials, also take a look at how to support iOS TouchID in your app!

Adding the functions

BUT NOTHING WOKRS RIGHT NOW? Yeah, how shall things work without a controller? So change our state to:

  .state('login', {
      url: '/login',
      templateUrl: 'templates/login.html',
      controller: 'LoginCtrl'
  })

As mentioned from a comment (thanks to Matthias!), we have to set our fallback route to /login, so that our login get’s called as first route. As Matthias said, this is not the best way for production apps, but for now include this below our states to make our app work:

$urlRouterProvider.otherwise('/login');

Now open up the controllers.js, and add our simple login controller:

.controller('LoginCtrl', function($scope) {
    $scope.data = {};

    $scope.login = function() {
        console.log('LOGIN user: ' + $scope.data.username + ' - PW: ' + $scope.data.password);
    }
});

Here we create our scope variable, which is connected to the form fields we created in the login. The action is already connected to the login button, so go ahead and try to login. For now this just logs the entered data. As you often want to verify the data with a server, we will create a simple service to verify the data. Open the services.js and add a new service:

.service('LoginService', function($q) {
    return {
        loginUser: function(name, pw) {
            var deferred = $q.defer();
            var promise = deferred.promise;

            if (name == 'user' && pw == 'secret') {
                deferred.resolve('Welcome ' + name + '!');
            } else {
                deferred.reject('Wrong credentials.');
            }
            promise.success = function(fn) {
                promise.then(fn);
                return promise;
            }
            promise.error = function(fn) {
                promise.then(null, fn);
                return promise;
            }
            return promise;
        }
    }
});

Ok this is a bit of code, but no magic. We create our loginService with one function loginUser(), which expects the name and password of the user. Obviously the whole promise construct is over the top for this simple use-case but when you want to verify the user to a REST server, you need to make it async. Therefore, it’s better to have it now already!

So in this case, we grant access to user/secret, and resolve our promise if the credentials fit our expected user details. Otherwise, the promise gets rejected.

The lines 12-18 are just a bit of syntactic sugar. I like the promise to have a success/error function, otherwise we could just use .then(..) and check the result, but with success and error the code is better to read in my opinion.

As result of our login function we return our promise, so now we must include the service in our LoginCtrl. Change our controller to this:

.controller('LoginCtrl', function($scope, LoginService, $ionicPopup, $state) {
    $scope.data = {};

    $scope.login = function() {
        LoginService.loginUser($scope.data.username, $scope.data.password).success(function(data) {
            $state.go('tab.dash');
        }).error(function(data) {
            var alertPopup = $ionicPopup.alert({
                title: 'Login failed!',
                template: 'Please check your credentials!'
            });
        });
    }
});

So here you can see how we use our service and promise correctly. First, we need to add the LoginService dependency, the $ionicPopup dependency for a simple popup and the $state for the transition to the next view. The login function now calls the loginUser function with the username and password entered in the form. Here we can use the success() and error() function for handling the login. If the credentials are as expected (user/secret), we navigate to the normal starting point of the tabs template, tab.dash, using the $state. If the credentials are wrong, we display a simple alert popup.

Now serve your app and try to login. EPIC! It just works ;)

Interested in learning how to build apps with the Ionic Framework? Check out my complete step-by-step video course Ionic by Doing!

So long, Simon