This tutorial gets you off the ground with Angular 2. We are going to use the official CLI (command line) tool to generate boilerplate code.
- Node.js up and running.
- NPM (Node package manager) or Yarn installed.
You can verify by typing:
If you get the versions Node 4.x.x and NPM 3.x.x. or higher you are all set. If not you have to get the latest versions.
Let’s move on to Angular. We are going to create a Todo app. We will be able to CRUD (create-read-update-delete) tasks:
Angular CLI is the best way to get us started. We can download the tool and create a new project by running:
Note The last command takes some minutes. Leave it running and continue reading this tutorial.
ng new will do a bunch of things for us:
- Initialize a git repository
- Creates an
package.jsonfiles with all the Angular dependencies.
- Setup TypeScript, Webpack, Tests (Jasmine, Protractor, Karma). Don’t worry if you don’t what they are. We are going to cover them later.
- It creates the
srcfolder with the bootstrapping code to load our app into the browser
- Finally, it does an
npm installto get all the packages into
Let’s run the app!
Open your browser on http://localhost:9000/ and you should see “Loading…” and then it should switch to “app works!”. Awesome!
Now let’s dive into the
src folder and get familiarized with the structure.
package.json file and take a look at the dependencies. We have all the angular dependencies with the prefix
@angular/.... There are other dependencies that are needed for Angular 2 to run, such as RxJS, Zone.js, and some others. We are going to cover them in their own posts.
We are building a SPA (single page application) so everything is going to be loaded into the
index.html. Let’s take a look in the
src/index.html. It’s pretty standard HTML5 code, except for two elements that are specific for our app:
base href is needed for Angular 2 routing to work properly. We are going to cover Routing in its own chapter.
<app-root> this is not a standard HTMl tag. It’s actually defined by our Angular App. It’s an Angular component. More on this later.
This is the part where our application starts bootstrapping (loading). Angular 2 can be used not just in browsers, but also on other platforms such as mobile apps or even desktop apps. So, when we start our application we have to specify what platform we want to target. That’s why we import:
platform-browser-dynamic. Notice that we are also importing the
The most important line is:
We are loading our
AppModule into browser platform. Now, let’s take a look at the
Every time we import from a directory (e.g.
index file will be loaded. In our case
./app/index.ts. This file only loads up other modules from our app directory such as
app.module. Let’s go to each of them in turn.
We are going to be using this file often. The most important part is the metadata inside the
@NgModule. There we have
- Declarations: goes all your components (e.g. AppComponent, TodoComponent)
- Imports: routes and modules go here.
- Bootstrap: list the component you want to load when the app starts. In our case is
This looks a little similar to the app module, but instead of
@NgModule we have
@Component. Again, the most important part is the value of the attributes (metadata). We have
styleUrls. This what they mean:
selector: is the name of the component. Remember that we had
<app-root>Loading...</app-root>? This is where is defined.
templateUrl: This is where the HTML code is.
<app-root>will be replaced for whatever you have in the template.
styleUrls: You can have styles that only applies to this component. This is pretty neat! You can change the styles with confidence knowing that it won’t bleed to other parts of the website.
AppComponent class you can define variables (e.g.
title) that are used in the templates (e.g.
Angular 2 Tutorial: Create a CRUD App with Angular CLI and TypeScript).
Let’s change the title from
Test your changes running:
You should see
Let’s create a new component to display the tasks. We can easily create by typing:
This command will create a new folder with 4 files:
Go ahead and inspect each one. It will look similar to the app components. Actually, let’s add our new component to the App component.
src/app/app.component.html, and remove the
<h1>Angular 2 Tutorial: Create a CRUD App with Angular CLI and TypeScript</h1> and replace it with:
If you have
ng serve running, it should automatically update and show
“todo works!” is not useful. Let’s change that by adding some HTML code to represent our todo tasks. Go to the
src/app/todo/todo.component.html file and copy-paste this HTML code:
This has the general structure about how we want to represent our tasks. Right now it has hard-coded tasks. We are going to slowly turn it into a dynamic app using Angular 2 data bindings. But before that let’s add some styling so things look better.
We are going to use a community maintained CSS for Todo apps. We can go ahead and download the CSS:
This will install a CSS file that we can use to style our Todo app and make it look nice. In the next section, we are going to explain how to use it with the
angular-cli.json is a special file that tells the Angular CLI how to build your application. You can define how to name your root folder, tests and much more. What we care right now, is telling the angular CLI to use our new CSS file from the node modules. You can do it by adding the following line into the
If you stop and start
ng serve, you will see that now it looks much better.
We have the skeleton so far. Now we are going to make it dynamic and allow users to add/remove/update/sort tasks. We are going to do two versions one serverless and another one using a Node.js/Express server. We are going to be using promises all the time, so when we use a real API, the service is the only one that has to change.
Let’s first start by creating a service that contains an initial list of tasks that we want to manage. We are going to use a
service to manipulate the data. Let’s create the service with the CLI by typing:
This will create two files:
For enabling the create-read-update-delete functionality, we are going to be modifying three files:
Let’s get started!
Let’s modify the
todo.service to be able to get tasks:
Now we need to change our todo component to use the service that we created.
The first change is importing our
TodoService and adding it to the providers. Then we use the constructor of the component to load the
TodoService. While we inject the service we can hold a private instance of it in the variable
todoService. Finally, we use it in the
getTodos method. This will make a variable
todos available in the template where we can render the tasks.
Let’s change the template so we can render the data from the service. Go to the
todo.component.html and change what is inside the
<li></li> for this one:
Also change the 32 in the template from:
replace it with:
When your browser updates you should have something like this:
Now, let’s go over what we just did. We can see that we added new data-binding into the template:
*ngFor: iterates through the
todosarray that we defined in the component and assigned in the
[ngClass]: applies a class when the expression evaluates to true. In our case, it uses class
[checked]: applies the
checkedattribute when the expression evaluates to true (
: render the todo title. The same happened with
Let’s start with the template this time. We have an input element for creating new tasks. Let’s listen to changes in the input form and when we click enter it creates the tasks.
Notice that we are using a new variable called
newTodo and method called
addTodo(). Let’s go to the controller and give it some functionality:
First, we created a private variable that we are going to use to get values from the input form. Then we created a new
todo using the todo service method
add. It doesn’t exist yet, so we are going to create it next:
This adds the new element into the
todos array and resolve the promise. That’s all. Go ahead a test it out creating a new todo element.
Let’s add an event listener to double click on each todo. That way, we can change the content. Editing is a tricky since we need to display an input form. Then when the user clicks enter it should update the value. Finally, it should hide the input and display the label with the updated value. Let’s do that by keeping a temp variable called
editing which could be true or false.
Notice that we are adding a local variable in the template
#updateTodo. Then we use it to get the value like
updateTodo.value and pass it to a function.
We want to update the variables on
blur (when you click somewhere else) or on
enter. Let’s add the function that actually updates the value in the component.
Also, notice that we have a new CSS class applied to the element called
editing. This is going to take care through CSS to hide and show the input element when needed.
We update the new todo’s title and after the service has process the update we set editing to false. Finally, we reload all the tasks again. Let’s add the
put action on the service. But we have an issue. We actually need a unique
id to identify each task. When we hook up the service with a real backend we will get that from the database. Let’s add it manually for now. We will call it
_id since that’s how MongoDB call it and will be easier to replace later.
Here we look for the todo with the matching
_id and update the title.
This is like the other actions. We add an event listenter on the destroy button:
Then we add the funtion in the component:
and finally, we add the method in the servie:
Now test it out in the browser!
It’s time to activate the routing. When we click on the
active button we want to show only the ones that are active. Similarly, we want to filter by
completed. Additionally, we want to the filters to change the route
AppComponent, we need to add the
router library and define the routes as follows:
First, we import the routing library. Then we define the routes that we need. We could have said
path: 'active', component: TodoComponent and the repeat the same for
completed. But instead, we define a parameter called
:status that could take any value (
active). Any other value path we are going to redirect it to
/all. That’s what the
Finally, we add it to the imports. So the app module uses it. Since the AppComponent is using routes. Now we need to define the
<router-outlet>. That’s the place there the routes are going to render the component based on the path (in our case
Let’s go to
app/app.component.html and replace
Test the app in the browser and verify that now the URL is by default
routerLink is the replacement of
href for our dynamic routes. We have set it up to be
/active. Notice that the expression is an array. You can pass each part of the URL as an element of the array.
The second part we are doing is applying the
selected class if the path matches the button. Yet, we haven’t populate the the
path variable yet. So let’s do that:
ActivatedRoute as a dependency and in the constructor. This gives us access to the all the
route params such as
path. Notice that we are using it in the
NgOnInit and set the path accordantly.
Go to the browser and check out that the URL matches the active button. But, it doesn’t filter anything yet. Let’s fix that.
To filter todos by active and completed, we need to pass a parameter to the
We added a new parameter
query, which takes the
path (active, completed or all). Then, we pass that parameter to the service. Let’s handle that in the service:
So we added a filter by
isDone when we pass either
active. If the query is anything else, we return all the todos tasks. That’s pretty much it, test it out!
One last UI functionality, clearing out completed tasks button. Let’s first add the click event on the template:
We referenced a new function
clearCompleted that we haven’t create yet. Let’s create it in the TodoComponent:
In the same way we have to create
deleteCompleted in the service:
We use the filter to get the active tasks and replace the
todos array with it.
That’s it we have completed all the functionality.
Angular CLI comes with a convenient command to deploy your app to Github pages.
If you want to build your app for production you can do:
That’s all folks!