This tutorial gets you off the ground with Angular. 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:
If the versions don’t match then you can remove previously installed angular CLI with the following commands:
Once you have the right version, do:
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 know 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 “Welcome to app!”. 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/.... Other dependencies are needed for Angular to run, such as RxJS, Zone.js, and some others. We are going to cover them in other posts.
We are building an 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 routing to work correctly. We are going to cover Routing later.
<app-root> this is not a standard HTML tag. Our Angular App defines it. It’s an Angular component. More on this later.
main.ts is where our application starts bootstrapping (loading). Angular 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 the browser platform. Now, let’s take a look at the
The app directory contains the components used to mount the rest of the application. In there the
<app-root> that we so in the
index.html is defined. Let’s start with
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 components you want to load when the app starts. In our case is
AppComponent 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
selector: is the name of the component. Remember that we had
<app-root>Loading...</app-root>? AppComponent is where it’s 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 apply to this component. This is pretty neat! You can change the styles with confidence knowing that it won’t bleed into other parts of the website.
AppComponent class you can define variables (e.g.
title) that are used in the templates (e.g.
Angular Tutorial: Create a CRUD App with Angular CLI and TypeScript).
Let’s change the title from
Welcome to Angular Tutorial: Create a CRUD App with Angular CLI and TypeScript!to
Angular Tutorial: Create a CRUD App with Angular CLI and TypeScript. Also, remove everything else.
Test your changes running:
You should see the new message.
Let’s create a new component to display the tasks. We can quickly create by typing:
This command will create a new folder with four files:
And it will add the new Todo component to the
Go ahead and inspect each one. It will look similar to the app components. Let ‘s add our new component to the App component.
src/app/app.component.html, and replace everything 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:
The above HTML code has the general structure about how we want to represent our tasks. Right now it has hard-coded todo’s. We are going to slowly turn it into a dynamic app using Angular data bindings.
Next, let’s add some styling!
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.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, then you will notice the changes.
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
<ul class="todo-list"> ... </ul> 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 TODO.
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:
The above code adds the new element into the
todos array and resolves the promise. That’s all. Go ahead a test it out creating a new todo element.
You might get an error saying:
To use the two-way data binding you need to import
FormsModule in the
app.module.ts. So let’s do that.
Now it should add new tasks to the list!
Let’s add an event listener to double-click on each todo. That way, we can change the content. Editing is 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 show 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 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 processed the update, we set editing to false. Finally, we reload all the tasks again. Let’s add the
put action on the service.
Now, we can edit tasks! Yay!
This is like the other actions. We add an event listenter on the destroy button:
Then we add the function to the component:
and finally, we add the method to the service:
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
AppModule, 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 then 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 where 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 collection.
What 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. ActivatedRoute 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.
You can generate all your assets for production running this command:
It will minify and concatenate the assets for serving the app faster.
If you want to deploy to a Github page you can do the following:
/angular-todo-app/ with the name of your project name. Finally, go to settings and set up serving Github pages using the
If when you compile for production you get an error like:
Then you need to change
public like this. This is because the Template in Angular is treated like a separate class.
That’s all folks!