-
Notifications
You must be signed in to change notification settings - Fork 1
08 Creating Notes
If we want to create any notes from within our own app, we'll need a form.
Let's replace the welcome text in notes.html with a form for creating a note.
app/notes/notes.html
<form>
<p>
<input type="text" name="title" id="note_title" placeholder="Title your note">
</p>
<p>
<textarea name="body_html" id="note_body_html"></textarea>
</p>
<div class="form-actions">
<input type="submit" name="commit" value="Create Note" class="btn btn-default">
</div>
</form>
We can fill out this form and click the button all day, but nothing is going to happen until we Angular-ify it.
Let's add a binding to the <form>
tag that we can use to post to the Nevernote API.
app/notes/index.html
<form ng-submit="commit()">
We've just wired it up to invoke a commit
function on the current scope. Although we set the controller on our <nav>
element, we haven't specified it here. We don't want to instantiate the same controller again though, so let's move the ng-controller
controller to the .container
div.
<div class="container" ng-controller="NotesController">
It will still instantiate the controller twice, because it's referenced in the route and again in this directive.
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/notes', {
templateUrl: 'notes/notes.html',
controller: 'NotesController'
});
}])
We don't need to do it both places, so let's remove it from the route.
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/notes', {
templateUrl: 'notes/notes.html'
});
}])
Now let's make that commit
function actually exist. Go back to notes.js
and add the function to the NotesController
, first with just a console.log()
to make sure the binding is hooked up correctly. Add it right under the call to $http.get
, still inside NotesController
.
app/notes/notes.js
$scope.commit = function() {
console.log('I am submitting the form');
};
If that's wired up, correctly, let's set it up to post some JSON to our API.
Angular's $http
service includes a method for making an HTTP POST request, predictably: $http.post()
.
Have a look at the official documentation for $http.
LAB: Look through this page, and make the commit()
function post a new note to the API. Don't worry about actually getting the data from the form just yet. We'll use some fake data to start.
Hint: The API endpoint is once again apiBasePath + notes
Hint2: The post data (the second argument to $http.post
) should look something like this:
var noteData = {
api_key: apiKey,
note: {
title: 'COOL TITLE',
body_html: 'LESS COOL BODY'
}
}
SOLUTION:
$scope.commit = function() {
console.log('I am submitting the form');
$http.post(nevernoteBasePath + 'notes', {
api_key: apiKey,
note: {
title: 'COOL TITLE',
body_html: 'LESS COOL BODY'
}
}).success(function(newNoteData){
console.log('New note posted');
console.log(newNoteData);
});
};
If you submit the form, you should see in the console that it posted and returned a JSON object with the new note we just made. But the list of notes on the sidebar didn't update. What gives?!
The sidebar is bound to loop over $scope.notes
, but we add our new note to $scope.notes
after we created it. Let's update the full list of notes in the .success()
callback:
$scope.notes.push(newNoteData);
Let's reload the page, and post a new note, to see what happens.
Strangely, the list does not automatically update when $scope.notes
is altered. We can fix this by accessing the current scope by some means other than $scope
. Angular lets us access an element's scope by wrapping it in a jQuery object and calling the scope()
method that AngularJS adds to jQuery. We aren't including jQuery right now, but we can use Angular's angular.element
method to wrap DOM elements in Angular's lite version of a jQuery object.
var sidebarScope = angular.element(document.getElementById("sidebar")).scope();
Now that we have our scope assigned to this new local variable, we can add our new note to the notes
array. Let's use Array#unshift
to add the new note the beginning of the array, rather than Array#push
, which appends it to the end.
sidebarScope.notes.unshift(newNoteData.note);
All told, our commit()
function should look like this:
$scope.commit = function() {
$http.post(nevernoteBasePath + 'notes', {
api_key: apiKey,
note: {
title: 'COOL TITLE',
body_html: 'LESS COOL BODY'
}
}).success(function(newNoteData){
var sidebarScope = angular.element(document.getElementById("sidebar")).scope();
sidebarScope.notes.unshift(newNoteData.note);
});
};
There sure is a lot of service-related stuff going on in this controller now. That funcationality deserves its own module, so let's extract it to an Angular service
module.
Up to this point, we've had the controller and routeProvider declarations chained to the module declaration in notes.js. But with a second controller, we can no longer continue to endlessly chain declarations.
LAB: Assign the result of angular.module
to a variable, and make all .controller
calls on that.