Implementing modern component-based architecture in your new or existing Angular 1.x web application is a breath of fresh air.
In this course, you are going to take a close look at Eggly, an Angular 1.x application for organizing bookmarks, and build it using modern patterns and practices, inspired by Angular 2's recommended architecture.
You will learn how to leverage ES6 in your Angular 1 applications through Babel, and fully understand the core patterns that are used in a composed modular web application.
This course will teach you how to leverage your existing knowledge of Angular, while preparing your mind (and applications!) for the future.
If you are interested, there is a companion guide that digs deeper into the patterns found in this course and Angular 2.
In this introductory lesson, we will discuss how the architectural concepts of Angular 2 can be applied to AngularJS 1.x. We will also take a brief tour of the concepts that we will be covering in this series as well as how the code is structured per lesson.
Angular 2 leverages new language features in ES6 and TypeScript so that we can organize and express our ideas better. By writing our Angular 1.x application in ES6, we can create a surprising resemblance to an Angular 2 application. To do this, we need to set up Webpack and Gulp to convert our code into something the browser can safely understand. In this lesson, we will learn how to configure Webpack to process our source code and then hook it into Gulp as part of our build system.
The entry point for any Angular 2 is a single, top-level component that all other components branch off of. We will apply this pattern to our Angular 1.x applications by creating our first component using the
.component syntax and adding it to our application to serve as our root component.
An Angular 2 cornerstone is component driven architecture and how we divide up our features into self-contained components and then fit them together. In this lesson, we will cover the basic structure of a component in an Angular 2 style as we build one from the ground up. Equally important, we will see how to integrate it into our application by adding it to our root component.
The simplest version of a component in Angular 2 is nothing more than a container for a template. When we need to introduce imperative logic into our component, we do that via an ES6 class. We accomplish the exact same thing in Angular 1.x by using an ES6 class to serve as a controller for a component. In this lesson, we will examine an Angular 2 component to establish the pattern and then illustrate the similarity as we build out our own controller in ES6.
In Angular, we want to keep our controllers lightweight and specific to the view that it is controlling. To accomplish this, we are going to refactor our categories collection into a CategoriesModel. A recurring theme in Angular 2 is that everything is "just a class". When we create our controllers and services in an Angular 2 style, they are also "just a class". We will see this in action as we convert our controller almost verbatim into a service.
In this lesson, we are going to talk about dependency injection in an Angular application in ES6. There is a gotcha that I want to point out that most people will run into especially if they have not spent a lot of time using a classical language. We will start with a contrived example and then anchor it back into our application when we modify our CategoriesModel to use the $q service to return a promise.
Angular 2 introduces the concept of inputs and outputs as a mechanism for components to communicate. The most significant advantage of this is that we can create presentation components that are void of any imperative logic as they rely entirely on their parent container component. We will learn how to create inputs and outputs in Angular 1 using isolated scope and the component binding syntax.
Angular exposes key events within a component's lifecycle so that we can apply our own custom logic. In this lesson, we will learn how to leverage component lifecycle hooks to adhere to best practices of keeping our initialization logic out of our constructor.
In Angular, our controllers should be small and focused on the view that it is controlling. We accomplish this by moving as much logic and state as we can into models. Angular 2 introduced observables and async pipes which make it easy to manage state and communicate that directly to our templates.
We can start to point our Angular 1 applications in that direction by binding to our models directly from within our controllers. In this lesson, we will see a simple example of this technique and a slightly more advanced case where we lose the lexical reference to the
Managing state is one of the hardest things to do in any application. Angular 2 tackles this problem by making it easy to implement a reactive, uni-directional data flow that favor immutable operations. We are moving in the right direction in Angular 1 by moving our state and logic to models but invariably this raises a question. If we are moving to an immutable world, how do you manage mutable operations like forms in Angular? In this lesson, we are going to learn a surprisingly simple technique to isolate state mutations within a component using component lifecycle hooks.
In Angular 2, we use observables to push new data to our components. In Angular 1, we occasionally need to notify a component that a collection has changed so that we can perform an operation at the component level.
For example, when we are editing or creating a bookmark, and we navigate to a new category, we are left in this awkward state of an incomplete edit.
We need to be notified when a new category is selected at the bookmark level so that we can reset the current bookmark. Even though we do not have the convenience of an observable to emit state changes to us, we can still spin up an event bus to let us know when we need to hit reset.
Traditionally you had to create DOM elements to test a directive but by shifting our focus to components, writing unit tests got a lot easier using $componentController within ngMocks. We can now test our component's controller with an easy to use API that does not require us to spin up any DOM elements to do so. In this lesson, we will see how our ES6 tests are transpiled, learn how to test a component using $componentController and talk about how to simulate lifecycle hooks.
Lukas Ruebbelke is a technology enthusiast and author of AngularJS in Action for Manning Publications. His favorite thing to do is get people as excited about new technology as he is. He is the co-organizer of the Arizona Software Community user group and host of multiple developer events in the Phoenix metro area.