I can't seem to manage to make a variable for the view with the info from a json file but I'm so close. I can echo out the information in the .subscribe()
-chain, but it won't set it to a variable, they just get undefined, what am I doing wrong?
I just want to load my json file into a variable in the component view. It was easy in Angular 1.
My service:
import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import 'rxjs/add/operator/map';
import {Observable} from 'rxjs/Rx';
@Injectable()
export class GullkornService {
result: any;
constructor(private http:Http) {
}
getGullkorn() {
let result = this.result;
this.http.get('./gk/gullkorn.json')
.map(res => res.json())
.subscribe(
val => this.result = val,
err => console.error(err),
() => console.log(this.result)); // this one echoes out what i want
console.log(this.result); // but this one doesnt, so i cant return it
}
}
And the landing component:
import { Component, OnInit } from '@angular/core';
import {Router, RouterOutlet} from '@angular/router';
import { HttpModule, JsonpModule } from '@angular/http';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { GullkornService } from '../../gullkorn-service.service';
import { FormsModule } from '@angular/forms';
import {Observable} from 'rxjs/Observable';
import "gsap";
declare var ease, TimelineMax,TweenMax,Power4,Power1,Power2,Power3,Bounce, Elastic:any;
@Component({
selector: 'gullkorn-visning',
providers: [GullkornService],
templateUrl: './landing.component.html',
styleUrls: ['./landing.component.css']
})
export class LandingComponent implements OnInit {
gullkorn: any;
constructor(GullkornService: GullkornService) {
this.gullkorn = GullkornService.getGullkorn();
console.log(this.gullkorn);
}
ngOnInit() {
}
}
Based on current code this is what I get:
I have the project here: github.
This is an async operation, so when you try to console.log the result it's undefined, as it is being run before the other console.log inside the subscription.
.subscribe(
val => this.result = val,
err => console.error(err),
() => console.log(this.result)); // is run sometimes later
console.log(this.result); // is run first
}
I would make some changes to your code... I would suggest you take care of the subscription in the component instead, this would be the best way to handle http-requests. So just map
in the service and return the observable to the component, remember to add return
statement :
getGullkorn() {
return this.http.get('./gk/gullkorn.json')
.map(res => res.json())
}
In your component I would suggest you move your service call in OnInit
instead. Here you can also notice that the values aren't instantly accessible outside the subscription as per comments in code. So if you want to manipulate your data somehow, you need to take that into consideration :)
ngOnInit() {
this.GullkornService.getGullkorn()
.subscribe(data => {
// is run sometimes later
this.gullkorn = data
});
// is run first
}
AS this is an async operation, so be prepared to use either ngIf
or the safe navigation operator in your view, since view is rendered before data has been retrieved.
So either wrap your code inside ngIf
:
<div *ngIf="gullkorn"></div>
or {{gullkorn?.someProperty}}