Reputation: 1516
I'm trying to get a list of news and then render them in the template of my component.
I was learning from this tutorial, which is a little bit out of date, http://chariotsolutions.com/blog/post/angular2-observables-http-separating-services-components/
The news item class looks like this
export class NewsItemComponent {
text: string;
date: Date;
author: string;
link: string
constructor(text: string,
date: Date,
author: string,
link: string) {
this.text = text;
this.date = date;
this.author = author;
this.link = link;
}
}
The service retrieving the data:
import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { NewsItemComponent } from './news-item/news-item.component';
@Injectable()
export class NewsService {
constructor(public http: Http) {
console.log('Creating NewsService');
}
getNews() {
let url = 'http://localhost/test-api/';
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
this.http.post(url, '', options)
// initial transform - result to json
.subscribe( (res:Response) => {
let articles: Array<any> = [];
res.json().map((articles: Array<any>) => {
articles.push(new NewsItemComponent('asd', new Date(), 'asdf', 'asdf'));
});
console.log('articles', articles);
return articles
});
}
}
The main component:
import { Component, OnInit, AfterViewInit, AfterViewChecked } from '@angular/core';
import { Http, Response, RequestOptions, Headers, Request, RequestMethod } from '@angular/http';
import { TranslateService } from 'ng2-translate/ng2-translate';
import { NewsItemComponent } from './news-item/news-item.component';
import { NewsService } from './news-service.service';
@Component({
selector: 'news-section',
templateUrl: './news-section.component.html',
styleUrls: ['./news-section.component.scss'],
providers: [ NewsService ]
})
export class NewsSectionComponent implements AfterViewInit {
articles: NewsItemComponent[];
constructor(translate: TranslateService, private http: Http, public newsService: NewsService) {
translate.setDefaultLang('en');
translate.use('en');
this.articles = [];
newsService.getNews().subscribe(res => this.articles = res);
}
}
And the view:
<section id="news" sectionVisible>
<div>
<h1>{{ 'Nav.News' | translate }}</h1>
</div>
<div class="news-wrapper clear-fix">
<div class="column carousel-cell" ngFor="#article of articles">
<article>
<a href="#" class="hovered">
<div class="bg-hover">
<p>
Visit
</p>
</div>
</a>
<h2>News title</h2>
<time>21.10.2015 16:30</time>
<p>
Etiam faucibus sodales leo, rutrum molestie nisi luctus in. Duis quis viverra diam, vitae hendrerit augue. Donec ultricies nisi vel placerat sodales. Donec varius convallis mauris egestas vulputate. Integer fermentum tincidunt hendrerit. Donec eget nisl
eros. Pellentesque a fringilla lorem.
</p>
</article>
</div>
</div>
</section>
Of course in the view the lorem ipsum parts will be changed by the data retrieved. But there is something wrong with the service:
newsService.getNews().subscribe(res => this.articles = res);
this line raises an error:
Property subscribe does not exist on type void
And I have no idea why it is caused. Any hints?
Upvotes: 1
Views: 57
Reputation: 10834
You need to remove the subscribe
method from your service. Services should only return the Observables, subscribing should be done in the actual component.
Subscribing to an Observable is equal to calling a function. You want to retrieve the result in your component, so that's where you need to subscribe. The service should only hold the logic to prepare the data after the HTTP call (calling for example res.json()
).
Service
getNews() {
let url = 'http://localhost/test-api/';
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(url, '', options)
.map(res => res.json());
}
Component:
newsService.getNews()
.subscribe( news => {
let articles: Array<any> = [];
news.map((articles: Array<any>) => {
articles.push(new NewsItemComponent('asd', new Date(), 'asdf', 'asdf'));
});
this.articles = articles
});
Upvotes: 1