If the versions don’t match then you can remove previously installed angular CLI with the following commands:

12

npm uninstall -g @angular/cliyarn global remove @angular/cli

Once you have the right version, do:

12

# create a new projectng new Todos --style=scss

Note The last command takes some minutes. Leave it running and continue reading this tutorial.

The command ng new will do a bunch of things for us:

Initialize a git repository

Creates an package.json files 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 src folder with the bootstrapping code to load our app into the browser

Finally, it does an npm install to get all the packages into node_modules.

Let’s run the app!

12

# builds the app and run it on port 9000ng serve ---port 9000

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

Open the 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.

src/index.html

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="/">

<app-root>Loading...</app-root>

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.

src/main.ts

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 AppModule from ./app.

The most important line is:

1

platformBrowserDynamic().bootstrapModule(AppModule);

We are loading our AppModule into the browser platform. Now, let’s take a look at the ./app/app.module.ts directory.

App directory

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 app.module

app.module.ts

We are going to be using this file often. The most important part is the metadata inside the @NgModule. There we have declarations, imports, providers and bootstrap.

Bootstrap: list the components you want to load when the app starts. In our case is AppComponent.

app.component.ts

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, templateUrl and styleUrls:

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.

Inside the 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.

<sectionclass="todoapp"><headerclass="header"><h1>Todo</h1><inputclass="new-todo"placeholder="What needs to be done?"autofocus></header><!-- This section should be hidden by default and shown when there are todos --><sectionclass="main"><ulclass="todo-list"><!-- These are here just to show the structure of the list items --><!-- List items should get the class `editing` when editing and `completed` when marked as completed --><liclass="completed"><divclass="view"><inputclass="toggle"type="checkbox"checked><label>Install angular-cli</label><buttonclass="destroy"></button></div><inputclass="edit"value="Create a TodoMVC template"></li><li><divclass="view"><inputclass="toggle"type="checkbox"><label>Understand Angular2 apps</label><buttonclass="destroy"></button></div><inputclass="edit"value="Rule the web"></li></ul></section><!-- This footer should hidden by default and shown when there are todos --><footerclass="footer"><!-- This should be `0 items left` by default --><spanclass="todo-count"><strong>0</strong> item left</span><!-- Remove this if you don't implement routing --><ulclass="filters"><li><aclass="selected"href="#/">All</a></li><li><ahref="#/active">Active</a></li><li><ahref="#/completed">Completed</a></li></ul><!-- Hidden if no completed items are left ↓ --><buttonclass="clear-completed">Clear completed</button></footer></section>

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.

Styling the todo app

We are going to use a community maintained CSS for Todo apps. We can go ahead and download the CSS:

1

npm install --save todomvc-app-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.

Adding global styles to angular.json

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 styles array:

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.

Todo Service

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:

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:

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:

UPDATE: on double click

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.

Routing and Navigation

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 /active or /completed URLs.

In 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 (all, completed, active). Any other value path we are going to redirect it to /all. That’s what the ** means.

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 TodoComponent).

Let’s go to app/app.component.html and replace <app-todo></app-todo> for <router-outlet></router-outlet>:

app/app.component.html

1

<router-outlet></router-outlet>

Test the app in the browser and verify that now the URL is by default http://localhost:9000/all.

Using routerLink and ActivatedRoute

routerLink is the replacement of href for our dynamic routes. We have set it up to be /all, /complete and /active. Notice that the expression is an array. You can pass each part of the URL as an element of the collection.

We added 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.

Replace /angular-todo-app/ with the name of your project name. Finally, go to settings and set up serving Github pages using the /docs folder:

Troubleshooting

If when you compile for production you get an error like:

123456789

The variable used in the template needs to be declared as "public". Template is treated as a separate Typescript class.ERROR in src/app/todo/todo.component.html(7,8): : Property 'newTodo' is private and only accessible within class 'TodoComponent'.src/app/todo/todo.component.html(19,11): : Property 'todos' is private and only accessible within class 'TodoComponent'.src/app/todo/todo.component.html(38,38): : Property 'activeTasks' is private and only accessible within class 'TodoComponent'.src/app/todo/todo.component.html(41,36): : Property 'path' is private and only accessible within class 'TodoComponent'.src/app/todo/todo.component.html(44,39): : Property 'path' is private and only accessible within class 'TodoComponent'.src/app/todo/todo.component.html(47,42): : Property 'path' is private and only accessible within class 'TodoComponent'.src/app/todo/todo.component.html(7,8): : Property 'newTodo' is private and only accessible within class 'TodoComponent'.

Then you need to change private to public like this. This is because the Template in Angular is treated like a separate class.

Adrian Mejia is a full-stack web developer located in Boston.
Currently working at Cisco as a Software Engineer.
Adrian enjoys writing posts about programming and technology.
Also, he likes to travel ✈️ and biking 🚴‍. Find out more here.