Services

Until an app is connected to a backend, it's not very useful. This is where Angular2 services come in.

Services:

  • remove data access from the component
  • give us an exportable, reusable way of accessing backend data
  • allow a way to normalize many different incoming data streams for all service consumers

To that end, Covalent provides several services to simplify routing and RESTful calls:

  • HttpInterceptorService
  • RESTService

In this lab, we will create our own MessagesService that inherits the covalent RESTService.

Setup

Stash away any items not needed for this lab

git stash

Checkout the repo at the start tag

git checkout tags/lab/mock-api/message-schema -b services-lab

Start the local angular-cli server:

ng serve

you should see:

Open a new tab or console. Start the Data Server in a new tab/console:

npm run start-api

You should see:

Finally, point a browser to http://localhost:4200

A login should load! Let's get to work!

Take a look at /src/services/messages.service.ts:

import { Injectable } from '@angular/core';
import { Response } from '@angular/http';
import { HttpInterceptorService } from '@covalent/http';

export interface IMessage {
  id?: number;
  title?: string;
  sender?: string;
  body?: string;
  received_at?: any;
}

@Injectable()
export class MessagesService {

  constructor(private _http: HttpInterceptorService) {}

  query(): any {
   return this._http.get('data/messages.json')
   .map((res: Response) => {
     return res.json();
   });
  }

  get(id: number): any {
   return this._http.get('data/messages.json')
   .map((res: Response) => {
     let message: any;
     res.json().forEach((s: any) => {
       if (s.id === id) {
         message = s;
       }
     });
     return message;
   });
  }
}

And point your browser to http://localhost:4200/messages to see the resulting data:

First thing to do is import the covalent RESTService:

import { HttpInterceptorService, RESTService } from '@covalent/http';

We can remove Response from the @angular/http library since RESTService takes care of it, but we need to import Headers in order to customize our REST calls.

import { Headers } from '@angular/http';

We need to add a link to our mock-api server. This has conveniently been supplied for us in ../config/api.config.

import { MOCK_API } from '../config/api.config';

Now we can make MessageService inherit the RESTService class:

export class MessagesService extends RESTService<IMessage> {

}

Since RESTService already implements query() and get(), we can remove those. Lets specify some parameters that are specific to the message service:

export class MessagesService extends RESTService<IMessage> {

  constructor(private _http: HttpInterceptorService) {
    super(_http, {
      baseHeaders: new Headers({'Accept': 'application/json'}),
      baseUrl: MOCK_API,
      path: '/messages',
    }); 
  }
}

Done! Our new messages.service.ts should now look like this:

import { Injectable } from '@angular/core';
import { Headers } from '@angular/http';
import { HttpInterceptorService, RESTService } from '@covalent/http';
import { MOCK_API } from '../config/api.config';

export interface IMessage {
  id?: number;
  title?: string;
  sender?: string;
  body?: string;
  received_at?: any;
}

@Injectable()
export class MessagesService extends RESTService<IMessage> {

  constructor(private _http: HttpInterceptorService) {
    super(_http, {
      baseHeaders: new Headers({'Accept': 'application/json'}),
      baseUrl: MOCK_API,
      path: '/messages',
    }); 
  }
}

Lets save and reload our browser: http://localhost:4200/messages

Real data from a real http endpoint!

Wait... Something is off. Lets use console.log to see if we can figure out what's happening.

in src/app/messages/messages.component.ts add a line after consuming your message packet from the service:

  loadMessages(): void {
    this._loadingService.register('messages.list');
    this._messagesService.query().subscribe((messages: IMessage[]) => {
      this.messages = messages;

      console.log(messages);

Open up your browser debug console, and drill into one of the array objects:

Now, open src/app/messages/messages.component.html and find where Sender and Received At are being displayed:

<template let-item let-last="last" ngFor [ngForOf]="messages">
  <md-nav-list>
    <a md-list-item [routerLink]="['/messages', item.id]">
      <md-icon md-list-avatar>message</md-icon>
      <h3 md-line> {{item.title}} </h3>
      <span hide-xs flex="30">
        {{item.sender}}
      </span>
      <span hide-xs flex="40" class="text-right md-body-1 pad-right">
        {{item.received_at | date:'short'}}
      </span>
      <span flex="10"></span>
    </a>
  </md-nav-list>
  <md-divider *ngIf="!last" md-inset></md-divider>
</template>

Notice anything?

Now that you've found the issue and fixed it, lets reload: http://localhost:4200/messages

w00t! Congratulations!

For the completed lab, go to https://github.td.teradata.com/ux/covalent-training/tree/feature/mock-api

Thanks!

results matching ""

    No results matching ""