-
Notifications
You must be signed in to change notification settings - Fork 1
14 Logging in
Thus far, we've just been passing a single API key around, but there isn't a way for a new user to come to our app and use it in place of the Rails app. Each user should have their own notes, instead of just seeing yours.
Let's add a separate view and controller with a form to log someone in.
You'll notice that angular-seed
gave us two sample views (view1
and view2
), so feel free to look at those for how these files should be structured.
Add a new directory at app/login
, and create two files inside named login.html
and login.js
, and fill them with this stuff:
app/login/login.html
<h3>Sign In</h3>
app/login/login.js
'use strict';
angular.module('notely.login', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/login', {
templateUrl: 'login/login.html',
controller: 'LoginController'
});
}])
.controller('LoginController', [function() {
}]);
Now, let's inform the main Angular module in app/app.js
of our new controller.
app/app.js
'notely.notes',
'notely.login'
And we need to add the new script to index.html
.
app/index.html
<script src="login/login.js"></script>
Now you should be able to go to http://localhost:8000/app/#/login, and see our <h3>Sign In</h3>
, big and green.
Let's add a login form.
LAB: Add a form to login.html
with a field for login
and password
.
- Extra credit: add a
ng-submit
form handler and$scope
function.- Extra credit hint: Don't forget to change the controller function definition signature to inject the
$scope
dependency.
- Extra credit hint: Don't forget to change the controller function definition signature to inject the
SOLUTION:
_app/login/login.html
<h3>Sign In</h3>
<form id="new_user" ng-submit="submit()">
<p>
<label for="username">Username</label><br>
<input type="text" name="username" autofocus="autofocus">
</p>
<p>
<label for="password">Password</label><br>
<input type="password" name="password">
</p>
<input type="submit" name="commit" value="Sign In" class="btn btn-default">
</form>
app/login/login.js
.controller('LoginController', [function() {
$scope.submit = function() {
// do something
};
}]);
This will complain that "$scope is not defined". Let's add the dependency:
(explain array syntax for minification)
.controller('LoginController', ['$scope', function($scope) {
There's a lot of things in our NotesBackend Service now, and there really isn't anything coupling it to our NotesController, so let's move it into app.js
Because the NotesController
module tracks its dependency back to NotesBackend
, we can still access it from the inside of the controller.
Refresh the page, and everything should still work—notes loading in the sidebar, adding and deleting notes, etc.
Nevernote provides a special way to login over the API that will return an API key if we authenticate with a valid username and password. Then we can use that key in subsequent requests.
Let's add the ability to hit that login endpoint, so we can present the users of our app with a working login page. Then we'll have a nice, multi-user app.
Let's implement the ng-submit
on the login form, so when a user puts in their login/password, we attempt to fetch the API key.
Note the additional dependency injection in LoginController
.
app/login/login.js
.controller('LoginController', function LoginController($scope, NotesBackend) {
$scope.user = {};
$scope.submit = function() {
NotesBackend.fetchApiKey($scope.user, function(){
debugger;
});
};
});
app/app.js
var notes = [];
var apiKey = '';
this.getApiKey = function() {
return apiKey;
};
this.fetchApiKey = function(userData, callback) {
var self = this;
$http.post(nevernoteBasePath+'session', {
user: {
username: user.username,
password: user.password
}
}).success(function(data){
console.log('got api key');
apiKey = data.api_key;
self.fetchNotes();
typeof callback === 'function' && callback();
});
};
Hook the form fields up to the model:
<p>
<label for="username">Username</label><br>
<input type="text" name="username" autofocus="autofocus" ng-model="user.username">
</p>
<p>
<label for="password">Password</label><br>
<input type="password" name="password" ng-model="user.password">
</p>
We're passing in a callback function that want to use to redirect to /notes
upon logging in.
To do this, we need to use the angular $location
module, so let's add it as a dependency to LoginController
and replace the debugger
with $location.path('notes')
.
app/login/login.js
.controller('LoginController', function LoginController($scope, $location, NotesBackend) {
$scope.user = {};
$scope.submit = function() {
NotesBackend.fetchApiKey($scope.user, function(){
$location.path('notes');
});
};
});
Now, if we reload the page from '/login', and provide correct credentials, we'll be taken to our note form, but our API key won't persist and our notes won't be loaded.