Roswell Studios

139 Fulton Street, Ste 132
New York, NY 10038

Angular Core Concepts

— July 1, 2016

Angular2 (or 1.5) for new or old users

If you have avoided Angular to date, good news! You won’t have to forget anything.
If you know all the differences between services and factories and controllers and directives, good news! Free up those brain cells!

This guide is not going to answer all the possible questions about Angular. Rather it is a mindset that I found very useful and is not present in the old angular docs or the little bit of documentation available on 2’s site.

First, ignore everything the old Angular websites tell you. Angular is, in its entirety, a data binding utility. It comes with a few classes that do stuff, but don’t confuse that with the core focus. Consider that 2 moved the routing to an external library, so being able to change the page contents wasn’t considered core enough for a SPA framework. This includes most obviously the ng-model=”someModel.variable” 2-way binding, the ng-click function binding, and the HTML to component controller binding, but one might consider the Dependency Injection thing a binding of variable name to class, and the binding of $ utilities to either the real thing or a mock object, and binding multiple applications together on to a page. Any Angular example will do a lot of things, but everything but the binding is not core Angular and you don’t have to do it that way if you don’t want to. Trying to apply The Angular Way to things has proven confusing as a lot of contradictory things have been put forward as the one true TAW. Don’t worry about it. If it works, it works.

import {SurveyQuestion} from './survey-question.model';

export class SurveyPage {
	id: number;
	name: string;
	survey: number;
	//page attributes

	//questions in this page

	public addQuestion() {var q1 = new SurveyQuestion(); q1.page_id =; this.questions.push(q1); return q1;};

Start by writing objects. Typescript is nice if you want, but Plain Old Javascript Objects skip over all the verbose import and export bits in these examples. Ideally test them as such. If the objects depend on each other, assume they are all together in a global scope. If they don’t depend on each other, treat each block as a separate app, write an entirely separate test for each. You will want to keep the dependencies as narrow as possible. All these mini-apps may all share the same libraries, if that helps break it up without duplicating code. There will be places where you want to use Angular library classes, but try and put that off for as long as possible. The longer you can, the longer your test cases don’t need to start up Angular to run. For example, you could have a lot of $http calls, or put in 1 ServerAPI class, and only inject $http there as late as possible. (or make your own $http spy so mock $http doesn’t need to call $digest.) Some of these objects are just isolated data bits and do very little, but others blend a lot of data objects and have functions you might imagine a user calling. Call those scope objects, or action objects, or whatever. The important part is you are not putting this inside an Angular $scope or controller.

import {Injectable} from 'angular2/core';
import {SurveySetup} from './survey-setup.model';
import {SURVEY} from './survey.mocksource';

export class SurveyService {
  getSurvey(id:number) {
    return Promise.resolve(SURVEY);

Now the binding comes in. A scope object will need some HTML for the user to see. The binding between HTML and one or more scope objects is a “component”.

import {Component, Input} from 'angular2/core';
import {SurveyQuestion} from './survey-question.model';

  selector: 'survey-question',
  template: `
edit question attributes here! 
<input name="" type="text" placeholder="name" /></div>
` }) 
export class QuestionComponent { 
@Input() question: SurveyQuestion;

use the Angular directives like ng-if (1 style) or ngIf (2 style, apparently) to bind the data and functions in the 100% Javascript application to the HTML in the template. Some of the HTML in a template isn’t a normal HTML tag. That’s just another component. The attributes in each component HTML control what data that component sees. The providers and directives in the component is the other part of the Dependency Injection. I said earlier the all-Javascript testing could assume everything was in the same global scope. This is what actually binds the objects to the same, not-global scope. You do need to plan ahead a bit, because of the limited scope thing you can have 2 different singleton instances. This enables you to put more than one app on the same page and is a good thing, but may come a bit of a surprise when 2 low level components turn out to not share what you assume is a single singleton.

Ideally, the component will have no code in it at all. The code it does have should be limited to binding your objects into various Angular utilities, such as calling the objects’ init functions when onInit. If it is code that necessary to process data from some of your objects in response to a user action, make that a new scope object, or a function in an existing object. All your code should be inside ng-click or listen. At worst, you might have functions like

Obj.function().then(function () {

although ng-click=”Myloader.load(Obj.function)” is probably the ideal solution for something so commonly used, anyway.

You should end up with a runnable, testable application with no UI, then an entirely separate Angular UI with no models or logic. Given that you have access to the Angular utilities, you might as well use them, so you probably won’t have complete separation, but you should try for code that not only doesn’t access the DOM, but doesn’t know/care that it is running a web browser or particular framework. Every input and output for your app would be model changes and function calls. Making dom changes in response to model changes and managing the templates is Angular’s thing.

Bonus: this concept works as well with React or, both of which are better than original flavor Angular without the verbosity and limited support related to Typescript.

Back to all