Skip to content

08b Service Modules

Dave Strus edited this page Aug 20, 2015 · 2 revisions

SOLUTION:

app/notes/notes.js

var noteApp = angular.module('notely.notes', ['ngRoute']);

noteApp.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/notes', {
    templateUrl: 'notes/notes.html'
  });
}]);

noteApp.controller('NotesController', function NotesController($scope, $http) {
  // controller stuff...
});

Angular Service Modules

Having done that, let's add the module and move all our Ajax code into it.

This will be a service module, rather than a controller module, and we'll call it NotesBackend. All of our Ajax calls will happen here, so we need to inject $http as a dependency.

noteApp.service('NotesBackend', function NotesBackend($http) {
});

We'll set up a local variable to hold our notes, and add functions to do the following:

  • Return the local array of notes.
  • Retrieve all notes from the Nevernote API and assign them to the array.
  • Post a new note to the Nevernote API and add it to the array.
noteApp.service('NotesBackend', function NotesBackend($http) {
  var notes = [];

  this.getNotes = function() {
    return notes;
  };

  this.fetchNotes = function() {
    // to do
  };

  this.postNote = function(noteData) {
    // to do
  };
});

LAB: Implement fetchNotes and postNote. (getNotes is given to you for free, courtesy of your generous Uncles Dave.)

SOLUTION:

You can move the $http.get and $http.post calls to these new functions, almost as-is. We just need to use the local notes array in place of $scope.notes, and we need to use our scope trick from earlier to keep the view in sync with our data.

  this.fetchNotes = function() {
    $http.get(nevernoteBasePath + 'notes?api_key=' + apiKey)
      .success(function(notesData) {
        notes = notesData;
        var sidebarScope = angular.element(document.getElementById("sidebar")).scope();
        sidebarScope.notes = notes;
      });
  };

  this.postNote = function(noteData) {
    var self = this;
    $http.post(nevernoteBasePath + 'notes', {
      api_key: apiKey,
      note: noteData
    })
    .success(function(newNoteData){
      self.fetchNotes();
      var sidebarScope = angular.element(document.getElementById("sidebar")).scope();
      sidebarScope.notes = notes;
    });
  };
});

Now we can make our NotesController quite svelte:

noteApp.controller('NotesController', function NotesController($scope, NotesBackend) {
  $scope.notes = [];
  NotesBackend.fetchNotes();

  $scope.commit = function() {
    var note = {
      title: 'Mega-hip title',
      body_html: 'Groovy body'
    };
    NotesBackend.postNote(note);
  };
});

When the controller is loaded, it assigns an empty array to a property of $scope for binding, and fetches the notes from the NotesBackend service module we just made.

The commit function gathers data from our form (well, it will eventually; it's still fake data at the moment), and passes that to the backend for processing.

It does feel a bit gross to me that the scope is being updated from the service module rather than the controller, so let's move that to a callback.