befriending AngularJS
Over the past few weeks, I've explored Angular's architecture while building a Twitter replica, a tool for non-profit dashboards, and a to-do application. While it's relatively easy to get an app up and running, it's far more difficult to understand just how the MVVM architecture works - and how to optimize it for more complex apps. To that end, I've developed a workflow for beginning a basic Angular app.
My Workflow for Architecting Angular.js Applications
- I always start with the view (likely a .html file), and define the DOM elements that I want to be in scope for my Angular application. Angular is flexible in defining its own scope -- unlike Backbone, you can utilize Angular for only pieces of your application. Defining Angular's scope is as easy as inserting an ng-app directive into the relevant html tag. In the view, I also define a ng-controller, as well as any user inputs that I wish to translate into action.
- I then build controllers in .js files. In the controllers, I define the functions that will update the $scope object by calling services and factories. Note that controllers should not handle the model updating or logic themselves; this should be outsourced to the services and factories.
- Finally, I write the services and factories that return an object with defined properties and methods. The $scope object can then be updated by setting a $scope property to a property of the returned object.
Factories:
Services and factories are extremely important in Angular. They should always be utilized (in lieu of the controller) for updating models. Models in Angular are essentially properties on the $scope object.
Factories in Angular return singletons, which are objects that are instantiated once at an application's runtime.
A basic implementation of a factory looks like this:
var app = angular.module('myapp', [ ]);
app.factory('myFactory', function ( ) {
var factoryInstance = { };
var factoryInstance.message = "";
// some code that adds properties or methods to the factoryInstance
factoryInstance.sayHello = function ( ) {
factoryInstance.message = "Hello!";
};
return factoryInstance;
};
Creating a factory returns an anonymous function that returns the 'factoryInstance' variable. One thing to remember here is that by default, using a factory to instantiate an object makes use of the functional instantiation pattern. You must create a new object and return it explicitly within the body of the factory.
A factory's methods are called in the controller:
app.controller('myController', function($scope) {
$scope.message = "";
$scope.sayHello = function ( ) {
factoryInstance.sayHello( );
$scope.message = factoryInstance.message;
};
};
The controller accesses the factoryInstance properties to update the $scope object, which acts as the model and passes along its information to the view.
<div ng-app= "myapp">
<div ng-controller= "myController">
<h1> {{ message }} </h1>
</div>
</div>