Lesson Monday

Now that we have a basic Angular project up and running, let's begin adding content. In this lesson, we'll learn how to add and display information using Angular components by turning the empty Angular application we constructed in the previous two lessons into a To Do List.

Display Properties in Templates

First off, let's update the template of our root component to reflect the purpose of our new application:

app/app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
  <div class="container">
    <h1>To Do List</h1>
  </div>
  `
})

export class AppComponent {

}

So far we've practiced hard-coding basic HTML in our templates, as seen above, but we also need to display dynamic data. For instance, let's include the current focus of our to do list. Since we're currently busy learning Angular, let's say our main focus is "Angular" right now.

We could write this directly in the template, like this:

app/app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
  <div class="container">
    <h1>To Do List</h1>
    <h3>For Epicodus Angular Homework</h3>
  </div>
  `
})

export class AppComponent {

}

However, this isn't the most efficient way to do this. After our JavaScript course is over, we'll probably change our focus to Rails, Android, .NET or React homework. After we graduate, we'd probably need to change it to "Internship Assignments". Because our current focus will change as time goes on, it would be better to store this in a variable and then display the variable in our template.

We can create a property to hold this information in the component's class:

app/app.component.ts
...

export class AppComponent {
  currentFocus: string = 'Angular Homework';
}

Here, we define a variable called currentFocus. We'll declare that it will hold a string, and set it to 'Angular Homework'. We can display this variable in our template with a double pair of curly brackets:

app/app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
   <div class="container">
      <h1>To Do List</h1>
      <h3>{{currentFocus}}</h3>
  </div>
  `
})

export class AppComponent {
  currentFocus: string = 'Angular Homework';
}

The double curly bracket tags tell Angular that they contain a known property on the component that can be found in that component's class declaration file.

When we need to focus on ".NET Homework", the template can remain the same and we'll only need to update the variable.

Variables Referring to Other Variables

It may seem counterproductive to do this for such a small piece of information, but you'll see the value of dynamically displaying data like this as our applications grow in size. For instance, what if we wanted to display data determined programmatically? Take today's date, for example. We wouldn't want to hard-code the date each day. Instead, it would be better for JavaScript to determine the date for us.

Let's also add the current date. We'll add variables to our template where we'd like to display month, day, and year values:

app/app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
   <div class="container">
      <h1>To Do List for {{month}}/{{day}}/{{year}}</h1>
      <h3>{{currentFocus}}</h3>
  </div>
  `
})

...

Then, we'll define these values in the component's class declaration by creating a new JavaScript Date object and retrieving the month, date, and year information from it using built-in JavaScript methods:

app/app.component.ts
...

export class AppComponent {
  currentFocus: string = 'Angular Homework';
  currentTime = new Date();
  month: number = currentTime.getMonth() + 1;
  day: number = currentTime.getDate();
  year: number = currentTime.getFullYear();
}

However, if we run $ gulp build and $ gulp serve to see our updated page, we receive an error like this:

epicodus-5:angular2-to-do staff$ gulp build
[10:51:11] Using gulpfile ~/Desktop/angular2-to-do/gulpfile.js
[10:51:11] Starting 'tsClean'...
[10:51:11] Finished 'tsClean' after 13 ms
[10:51:11] Starting 'ts'...
app/app.component.ts(19,19): error TS2663: Cannot find name 'currentTime'. Did you mean the instance member 'this.currentTime'?
app/app.component.ts(20,17): error TS2663: Cannot find name 'currentTime'. Did you mean the instance member 'this.currentTime'?
app/app.component.ts(21,18): error TS2663: Cannot find name 'currentTime'. Did you mean the instance member 'this.currentTime'?
[10:51:12] 'ts' errored after 1.75 s
[10:51:12] Error: Command `tsc` failed with exit code 2
    at ChildProcess.exithandler (child_process.js:202:12)
    at emitTwo (events.js:100:13)
    at ChildProcess.emit (events.js:185:7)
    at maybeClose (internal/child_process.js:850:16)
    at Socket.<anonymous> (internal/child_process.js:323:11)
    at emitOne (events.js:90:13)
    at Socket.emit (events.js:182:7)
    at Pipe._onclose (net.js:477:12)

Oh no! Let's look at this a more closely. The error message states Cannot find name 'currentTime' for the following three lines of code:

app/app.component.ts
...
  month: number = currentTime.getMonth() + 1;
  day: number = currentTime.getDate();
  year: number = currentTime.getFullYear();
...

Angular cannot find our currentTime variable in the lines after it's defined, even though it's right above these other variables! What gives?!

Notice what else the error message states: ...Did you mean the instance member 'this.currentTime'?

Let's try referencing this.currentTime instead of currentTime, per the error message's suggestion, in these three lines:

app/app.component.ts
...
  month: number = this.currentTime.getMonth() + 1;
  day: number = this.currentTime.getDate();
  year: number = this.currentTime.getFullYear();
...

And hey, it works this time:

angular-to-do-date-successfully-displayed

In Angular, when a variable in a component's class declaration references another variable in the class, it must be prefaced with the this keyword.

Dot Notation in Component Templates

Let's create our first Task. For now, we can package this in an object literal, like this:

app/app.component.ts
...

export class AppComponent {
  currentFocus: string = 'Angular Homework';
  currentTime = new Date();
  month: number = this.currentTime.getMonth() + 1;
  day: number = this.currentTime.getDate();
  year: number = this.currentTime.getFullYear();
  firstTask = {
    description: "Finish weekend Angular homework for Epicodus course"
  }
}

Then we can use dot notation to access the firstTask properties directly in the template:

app/app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <div class="container">
     <h1>To Do List for {{month}}/{{day}}/{{year}}</h1>
     <h3>{{currentFocus}}</h3>
     <ul>
       <li>{{firstTask.description}}</li>
     </ul>
   </div>
  `
})

...

If we look in the browser, we'll see our new task.

first-task-with-dot-notation

Nice work! Now that we understand how to display information in our templates (also referred to as a view in the MVC architecture), we'll begin to create more complex information to show our users. In the next lesson, we'll implement a Task model into our To Do List application.


Example GitHub Repo for Angular 2 To Do List