2

I've followed the tutorial on the angular site (https://angular.io/guide/http) but I can't achieve what I want since I have an error that I don't understand. I've put my text file in the assets doc and created a config.json file where I entered the code from the tutorial. I get errors in my service.ts file and component.ts file aswell. Please help me understand my errors and the tutorial.

Component.ts

import { Component, OnInit } from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {HttpClient, HttpErrorResponse, HttpResponse} from '@angular/common/http';
import {GeneralService} from '../general.service';

@Component({
  selector: 'app-general',
  templateUrl: './general.component.html',
  styleUrls: ['./general.component.css']
})
 export interface General {
  generalUrl: string;
  textfile: string;
}
 export class GeneralComponent implements OnInit {
  title = 'Introduction';
  generalUrl = 'assets/project_description.txt';
  general: General;
  generalService: GeneralService;

 constructor(private http: HttpClient) { }

 ngOnInit() {
}

 getGeneral() {
  return this.http.get(this.generalUrl);
}

 showGeneral() {
  this.generalService.getGeneral()
   .subscribe(data => this.general = {
     generalUrl: data['generalUrl'],
     textfile: data['textfile']
   });
}

showGeneralResponse() {
 this.generalService.getGeneralResponse()
  .subscribe(resp => {
    const keys = resp.headers.keys();
    this.headers = keys.map(key =>
    `${key}: ${resp.headers.get(key)}`);
  this.config = {
  });
 }
}

On my showGeneralResponse() function headers and config are unresolved variables

Service.ts

import { Injectable } from '@angular/core';
import {General} from './general/general.component';
import {HttpResponse} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class GeneralService {

  constructor() { }
  getGeneral() {
    return this.http.get<General>(this.generalUrl);
  }
  getGeneralResponse(): Observable<HttpResponse<General>> {
    return this.http.get<General>(
      this.generalUrl, { observe: 'response'}
    );
  }
}

In getGeneral() and getGeneralresponse() functions I have http and generalUrl who are unresolved variables

But in my config.json file I have no error

config.json

 "generalUrl": "api/general",
 "textfile": "assets/project_description.txt"

I also would like to know which function to put in my html file so my application would display me my file text

7
  • please get me your error Commented Mar 20, 2018 at 8:54
  • you want read config.json data with HttpClient? Commented Mar 20, 2018 at 9:02
  • In my showGeneralResponse() function -> showGeneralResponse() { this.generalService.getGeneralResponse() .subscribe(resp => { const keys = resp.headers.keys(); this.**headers** = keys.map(key => ${key}: ${resp.headers.get(key)}); **this.general** = { }); } the error is in headers and it says that it's an unresolved variable And I don't know what to put in the brackets of this.general Commented Mar 20, 2018 at 9:11
  • @LucieSchaffner we don't need you to reformat the error, all we need is the error trace. Could you please post it in your question ? And in full text, not as an image please Commented Mar 20, 2018 at 9:13
  • please change getGeneral method like this : getGeneral() { return this.http.get(this.generalUrl).map((res: Response) => res.json()); } Commented Mar 20, 2018 at 9:16

3 Answers 3

2

Lucie, I'm in hurry, (I supouse the problem is that Angular can't find the file data.json). I put the easer example I know:

//app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {HttpClientModule} from '@angular/common/http';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [DataService,],
  bootstrap: [AppComponent]
})
export class AppModule { }

//DataService.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class DataService {
    constructor(private http: HttpClient) { }
    getData() {
        return this.http.get('../assets/data.json')
    }
}
//app.compontent.ts
import { Component, OnInit } from '@angular/core';
import {DataService} from './data.service'
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  data:any;
  constructor(private dataService:DataService){}
  ngOnInit(){
    this.dataService.getDataDos(null).subscribe(res=>{
        this.data=res;
    })
  }
  }
}

//app.component.html
{{data |json}}

//data.json (in folder assets/)
[
    {"key":"uno"},
    {"key":"dos"},
    {"key":"tres"},
    {"key":"cuatro"},
    {"key":"cinco"}
]
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much you've helped me a lot ! I've found my mistake, I didn't import HttpModule in app.module.ts but HttpClient
1

@Lucie Shaffner 1.- the json must be a json, see the "{" and the "

{
    generalUrl: "api/general",
    textfile: "assets/project_description.txt"
}

2.-You have defined the variable "generalUrl" in your component, but not in the service.

3.-If you want to use a Service in a component you must inject in the constructor

//In your component

//remove the line below
//generalService: GeneralService;

//And change the cosntructor
constructor(private http: HttpClient,private generalService:GeneralService) { }

4.-You must cal lthe function this.showGeneral() in your ngOnInit() or never happens

5.- Declare the export interface before the component

import { Component, OnInit } from '@angular/core';
...
//Move export inferface here
 export interface General {
  generalUrl: string;
  textfile: string;
}

@Component({
  selector: 'app-general',
  templateUrl: './general.component.html',
  styleUrls: ['./general.component.css']
})
 export class GeneralComponent implements OnInit {
...
}

6 Comments

It helped a lot, I've corrected a few mistakes and I can understand better my errors but I still can't figure out what to do with my showGeneralResponse() function so I commented it and I get this error : ERROR in src/app/general/general.component.ts(6,1): error TS1206: Decorators are not valid here.
@Lucie, you must declare the "interfaces" BEFORE the @ Component (I update my answer)
Thank you very much it fixed the error But how can I ask my text file to display itself on my app now ? How shoul I declare it in my html and which function ?
You have a variable this.generalData. If in your general.component.html you write {{generalData.generalUrl}}{{generalData.textfile}} you can see the value of the variables.
I've done everything you told me and it compiled well with no error but it displays nothing, even a simple <h1> Hello <h1> And I can't find my error I've been through my code a few times and even recreated a new project
|
1

There is a library which allows you to use HttpClient with strongly-typed callbacks.

The data and the error are available directly via these callbacks.

A reason for existing

When you use HttpClient with Observable, you have to use .subscribe(x=>...) in the rest of your code.

This is because Observable<HttpResponse<T>> is tied to HttpResponse.

This tightly couples the http layer with the rest of your code.

This library encapsulates the .subscribe(x => ...) part and exposes only the data and error through your Models.

With strongly-typed callbacks, you only have to deal with your Models in the rest of your code.

The library is called angular-extended-http-client.

angular-extended-http-client library on GitHub

angular-extended-http-client library on NPM

Very easy to use.

Sample usage

The strongly-typed callbacks are

Success:

  • IObservable<T>
  • IObservableHttpResponse
  • IObservableHttpCustomResponse<T>

Failure:

  • IObservableError<TError>
  • IObservableHttpError
  • IObservableHttpCustomError<TError>

Add package to your project and in your app module

import { HttpClientExtModule } from 'angular-extended-http-client';

and in the @NgModule imports

  imports: [
    .
    .
    .
    HttpClientExtModule
  ],

Your Models

//Normal response returned by the API.
export class RacingResponse {
    result: RacingItem[];
}

//Custom exception thrown by the API.
export class APIException {
    className: string;
}

Your Service

In your Service, you just create params with these callback types.

Then, pass them on to the HttpClientExt's get method.

import { Injectable, Inject } from '@angular/core'
import { RacingResponse, APIException } from '../models/models'
import { HttpClientExt, IObservable, IObservableError, ResponseType, ErrorType } from 'angular-extended-http-client';
.
.

@Injectable()
export class RacingService {

    //Inject HttpClientExt component.
    constructor(private client: HttpClientExt, @Inject(APP_CONFIG) private config: AppConfig) {

    }

    //Declare params of type IObservable<T> and IObservableError<TError>.
    //These are the success and failure callbacks.
    //The success callback will return the response objects returned by the underlying HttpClient call.
    //The failure callback will return the error objects returned by the underlying HttpClient call.
    getRaceInfo(success: IObservable<RacingResponse>, failure?: IObservableError<APIException>) {
        let url = this.config.apiEndpoint;

        this.client.get(url, ResponseType.IObservable, success, ErrorType.IObservableError, failure);
    }
}

Your Component

In your Component, your Service is injected and the getRaceInfo API called as shown below.

  ngOnInit() {    
    this.service.getRaceInfo(response => this.result = response.result,
                                error => this.errorMsg = error.className);

  }

Both, response and error returned in the callbacks are strongly typed. Eg. response is type RacingResponse and error is APIException.

You only deal with your Models in these strongly-typed callbacks.

Hence, The rest of your code only knows about your Models.

Also, you can still use the traditional route and return Observable<HttpResponse<T>> from Service API.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.