Fork me on GitHub
Note: The Socially 2 tutorial is no longer maintained. Instead, we have a new, better and comprehensive tutorial, integrated with our WhatsApp clone tutorial: WhatsApp clone tutorial with Ionic 2, Angular 2 and Meteor (we just moved all features and steps, and implemented them better!)

Dynamic Templates

Note: If you skipped ahead to this section, click here to download a zip of the tutorial at this point.

Now it's time to make the web page dynamic — with Angular 2.

This step will still be focusing on client side Angular tools. The next one will show you how to get the full stack power of Meteor.

Data in the View

In Angular, the view is a projection of the model through the HTML template. This means that whenever the model changes, Angular refreshes the appropriate binding points, which updates the view.

Let's change our template to be dynamic:

3.1 Add dynamic html to the App component client/imports/app/app.component.html
1
2
3
4
5
6
7
8
9
<div>
  <ul>
    <li *ngFor="let party of parties">
      {{party.name}}
      <p>{{party.description}}</p>
      <p>{{party.location}}</p>
    </li>
  </ul>
</div>

We replaced the hard-coded party list with the NgFor directive and two Angular expressions:

  • The *ngFor="let party of parties" attribute in the li tag is an Angular repeater directive. The repeater tells Angular to create a li element for each party in the list using the li tag as the template.
  • The expressions wrapped in the double curly braces ( \{{party.name}} and \{{party.description}} ) will be replaced by the value of the expressions.

Angular 2 has common directives that provide additional functionality to HTML. These include ngFor, ngIf, ngClass, form directives (which will be heavily used on the 4th step) and more found in the @angular/common package. Those common directives are globally available in every component template so you don't need to import them manually into the component's view, in comparison to a custom directive or routing directives.

Component data

Now we are going to create our initial data model and render it in the view. This code will go inside of our AppComponent class constructor. A constructor is a function that runs when a class is loaded, thus it loads the initial data for the class.

We can attach data with the context this, referring to the AppComponent class:

3.2 Load parties data into app client/imports/app/app.component.ts
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  selector: 'app',
  template
})
export class AppComponent {
  parties: any[];
 
  constructor() {
    this.parties = [
      {'name': 'Dubstep-Free Zone',
        'description': 'Can we please just for an evening not listen to dubstep.',
        'location': 'Palo Alto'
      },
      {'name': 'All dubstep all the time',
        'description': 'Get it on!',
        'location': 'Palo Alto'
      },
      {'name': 'Savage lounging',
        'description': 'Leisure suit required. And only fiercest manners.',
        'location': 'San Francisco'
      }
    ];
  }
}

Run the app again.

$ meteor

You'll see the data model, parties, is now instantiated within the AppComponent component.

As you probably noticed, we defined parties with a any[]. Little disclaimer. That's a TypeScript specific thing and it's called Type.

What parties: any[] means? It tells to your IDE and TypeScript compiler that parties property is an array of any value. It could be an Object, Number etc.

In one of next chapters we will explain to you a lot more about Types.

Without this your IDE or console would say something like:

client/app.ts (13, 8): Property 'parties' does not exist on type 'AppComponent'.

Although we haven't done much, we connected the dots between the presentation, the data, and the business logic.

Summary

You now have a dynamic app that features a full component.

But, this is still all client side — which is nice for tutorials, but in a real application we need to persist the data on the server and sync all the clients with it.

So, let's go to step 3 to learn how to bind our application to the great power of Meteor.