Forward Advance Learning

AJAX - with a Service

In this section, we will use TypeScript to compose an AJAX service.

Creating the connection service

This service wishes to connect to the internet, and so needs to be able to talk to http. In order to do this we need to inject the necessary HTTP services into our app module. We're going to use JSONP, because we want to talk to a service that doesn't support CORS, but the process is the same with regular AJAX.

First import the Jsonp module and make it available to our app by adding it to the global module (app.module.ts). I'm importing the Http module and the forms module here too for good measure.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule, JsonpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { FlickrComponent } from './flickr/flickr.component';
import { FlickrService } from './flickr.service';
@NgModule({
declarations: [
AppComponent,
FlickrComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
JsonpModule
],
providers: [FlickrService],
bootstrap: [AppComponent]
})
export class AppModule { }

Creating the Service and Making it Injectable

Now we can create our service. Here is a super simple weather.service.ts

import {Injectable} from '@angular/core';
import {Jsonp} from '@angular/http';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
@Injectable()
export class WeatherService {
constructor(private jsonp: Jsonp) {
}
get(location:string) {
var url = [
"http://api.openweathermap.org/data/2.5/weather?q=",
location,
"&APPID=57d36da6b8187a992393dc6a0f4c96c3",
"&callback=JSONP_CALLBACK"].join('')
return this.jsonp.get(url)
.map((res) => res.json());
}
}

Notice the @Injectable decorator. This is essentially an empty decorator. TypeScript will only emit typing metadata if there is a decorator that might depend on it. Using this decorator forces TypeScript to emit the metadata, which allows Angular to determine the types for injection later.

Injecting the Service

Now we have our service, we can inject it into a weather component (weather.component.ts).

We add it to the list of Providers. This makes it injectable. Then we

import {Component} from '@angular/core';
import {WeatherService} from './weather.service';
@Component({
selector: 'weather',
template: `
<pre>{{weather | json}}</pre>
`,
directives: [],
providers: [WeatherService]
})
export class WeatherComponent {
constructor(public weather: WeatherService) {
var vm = this;
this.weather.get(this.loc)
.subscribe(data => {
this.weather = data;
});
}
}
}

Exercise - Flickr

We are going to use the Flickr API to pull a list of images about a tag.

The flickr JSONP endpoint looks like this:

http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=JSONP_CALLBACK

  1. First provide JSONP to app.module.ts.
  2. Now inject Jsonp into your constructor.
  3. In the constructor, make your call, like this: jsonp.get(url).
  4. Store the result in the component. feed = response.json() See above if you don't know where to put this line.
  5. Now in your template, put a line like this: {{feed}}. This will output the JSON feed onto the page.

Extension - List the cats

The JSON feed that comes from the server contains an items attribute, which is an array. Use ngFor to loop over the array

Harder Extension - Allow the user to search for a tag.

The URL has a tag parameter embedded in it. Create a search field with a button. When the user clicks search, trigger a JSONP request that will perform the search.

Exercise - Routing

You can navigate to a particular URL using the Router service. this.router.navigateByUrl('/flickr/:cats');

Extend your flickr app so that when you do a search it updates the URL to the search term. You now have a sharable URL that you can pass around.