Lesson Tuesday

In the last lesson, we explored how to dynamically display data in our Angular templates. We also created our first Task using an object literal.

...
  firstTask = {
    description: "Finish weekend Angular homework for Epicodus course"
  }
...

However, because we'll eventually make many Task objects, it would make more sense to create a Task class with a reusable constructor. This class will function as our model.

As we learned in the Modern JavaScript MVCs lesson, the model represents the data being displayed in the application. In a to do application, we'll need Task data.

Creating a Model

We'll start by adding a Task class declaration to our existing root component file, removing our previous object literal. We'll also expand our Tasks to include two properties instead of one:

  • A boolean called done with a default value of false.
  • A string named description containing details about the Task.

Add the following code at the end of app.component.ts:

app/app.component.ts
...
export class Task {
  public done: boolean = false;
  constructor(public description: string) { }
}

Our new model class resides outside of the AppComponent class. It also includes the export keyword so other areas of our application may access it.

Let's use our Task constructor to create our first Task object. Replace the firstTaskproperty with the following code:

app/app.component.ts
...

export class AppComponent {
  ...
  firstTask: Task = new Task("Finish weekend Angular homework for Epicodus course");
}
...

Notice that we now define our firstTask variable as the Task type. Because we've exported a Task class, Task is now a valid data type for variables. When we refresh the browser, everything should still be working.

Separating Out the Model

While this works fine, it's not ideal. What if multiple components need to access the model? Also, what if we had a really large application? It would be hard to find this model if the code is buried in one of many components. Our code would be harder to read and reason about. We should follow the principle of separation of concerns; our components shouldn't be concerning themselves with model data. Our components should just be focused on how the application looks and behaves.

Let's create a new file called task.model.ts and put it inside a new directory called models (which should be inside our app directory). Model file names should be lowercase and should be the name of the class followed by a .model.ts extension.

Now we'll move our Task model from the root component (app.component.ts) into our new dedicated model file (task.model.ts):

app/models/task.model.ts
export class Task {
  public done: boolean = false;
  constructor(public description: string) { }
}

Next we need to add an import statement to app.component.ts so it knows about the model:

app/app.component.ts
import { Component } from '@angular/core';
import { Task } from './models/task.model';
...

If we refresh the browser, everything is still working.

We should always keep our models separate from our components. This makes our code more readable, easy to reason about, and also makes it easier to expand our application.

We can now define data with a model and dynamically display the data in a view. In the next lesson, we'll add more Tasks to our list and explore directives that will allow us to add loops and conditionals directly to our component templates.