web-dev-qa-db-fra.com

Charger json à partir d'un fichier local avec http.get () dans angular 2

J'essaie de charger un json local avec http.get() dans angular 2. J'ai essayé quelque chose, que j'ai trouvé ici sur la pile. Il ressemble à ceci:

c'est mon app.module.ts où je import le HttpModule et le JsonModule de @angular/http:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule, JsonpModule } from '@angular/http';
import { RouterModule, Routes } from '@angular/router';

import { AppComponent } from './app.component';
import { NavCompComponent } from './nav-comp/nav-comp.component';
import { NavItemCompComponent } from './nav-comp/nav-item-comp/nav-item-comp.component';


@NgModule({
    declarations: [
        AppComponent,
        NavCompComponent,
        NavItemCompComponent
    ],
    imports: [
        BrowserModule,
        FormsModule,
        HttpModule,
        JsonpModule,
        RouterModule.forRoot(appRoutes)
    ],
    providers: [],
    bootstrap: [AppComponent]
})

export class AppModule { }

Dans mon composant je importHttp et Response de @angular/http. Ensuite, j'ai une fonction appelée loadNavItems(), où j'essaie de charger mon json avec un chemin relatif en utilisant http.get() et d'imprimer le résultat avec console.log(). La fonction est appelée dans ngOnInit():

import { Component, OnInit } from '@angular/core';
import { Http, Response } from '@angular/http';

@Component({
    selector: 'app-nav-comp',
    templateUrl: './nav-comp.component.html',
    styleUrls: ['./nav-comp.component.scss']
})
export class NavCompComponent implements OnInit {

    navItems: any;

    constructor(private http: Http) { }

    ngOnInit() {
        this.loadNavItems();
    }

    loadNavItems() {
        this.navItems = this.http.get("../data/navItems.json");
        console.log(this.navItems);
    }
}

Mon fichier json local ressemble à ceci:

[{
        "id": 1,
        "name": "Home",
        "routerLink": "/home-comp"
    },
    {
        "id": 2,
        "name": "Über uns",
        "routerLink": "/about-us-comp"
    },
    {
        "id": 3,
        "name": "Events",
        "routerLink": "/events-comp"
    },
    {
        "id": 4,
        "name": "Galerie",
        "routerLink": "/galery-comp"
    },
    {
        "id": 5,
        "name": "Sponsoren",
        "routerLink": "/sponsoring-comp"
    },
    {
        "id": 6,
        "name": "Kontakt",
        "routerLink": "/contact-comp"
    }
]

Il n'y a aucune erreur dans la console, je reçois juste cette sortie: enter image description here

Dans mon modèle html je voudrais boucler les éléments comme ceci:

<app-nav-item-comp *ngFor="let item of navItems" [item]="item"></app-nav-item-comp>

J'ai fait cela avec une solution que j'ai trouvée ici sur la pile, mais je ne sais pas pourquoi cela ne fonctionne pas?

MODIFIER LE CHEMIN RELATIF: J'ai aussi un problème avec mon chemin relatif, mais je suis sûr que c'est le bon quand j'utilise ../data/navItems.json . Dans la capture d'écran, vous pouvez voir le nav-comp.component.ts, où je charge le json en utilisant le chemin relatif du fichier json qui se trouve dans le dossier appelé data? Quel est le problème, la console affiche une erreur 404, car elle ne trouve pas mon fichier json à partir du chemin relatif?

enter image description here

41
webta.st.ic

MA PROPRE SOLUTION

J'ai créé un nouveau component appelé test dans ce dossier:

enter image description here

J'ai également créé une maquette appelée test.json Dans le dossier assests créé par angular cli (Important):

enter image description here

Cette maquette ressemble à ceci:

[
        {
            "id": 1,
            "name": "Item 1"
        },
        {
            "id": 2,
            "name": "Item 2"
        },
        {
            "id": 3,
            "name": "Item 3"
        }
]

Dans le contrôleur de mon composant testimport suivez rxjs comme ceci

import 'rxjs/add/operator/map'

Ceci est important, car vous devez map votre response à partir de l'appel http get, Vous obtenez donc un json et pouvez le boucler dans votre ngFor. Voici mon code pour charger les données fictives. J'ai utilisé httpget et j'ai appelé mon chemin vers la maquette avec ce chemin this.http.get("/assets/mock/test/test.json"). Après cela, je map la réponse et subscribe la. Ensuite, je l'assigne à ma variable items et je la boucle avec ngFor dans mon template. J'exporte également le type. Voici tout mon code de contrôleur:

import { Component, OnInit } from "@angular/core";
import { Http, Response } from "@angular/http";
import 'rxjs/add/operator/map'

export type Item = { id: number, name: string };

@Component({
  selector: "test",
  templateUrl: "./test.component.html",
  styleUrls: ["./test.component.scss"]
})
export class TestComponent implements OnInit {
  items: Array<Item>;

  constructor(private http: Http) {}

  ngOnInit() {
    this.http
      .get("/assets/mock/test/test.json")
      .map(data => data.json() as Array<Item>)
      .subscribe(data => {
        this.items = data;
        console.log(data);
      });
  }
}

Et ma boucle dans c'est template:

<div *ngFor="let item of items">
  {{item.name}}
</div>

Cela fonctionne comme prévu! Je peux maintenant ajouter plus de fichiers fictifs dans le dossier assests et changer simplement le chemin d'accès pour l'obtenir en tant que json. Notez que vous devez également importer les HTTP et Response dans votre contrôleur. La même chose dans votre app.module.ts (principal) comme ceci:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpModule, JsonpModule } from '@angular/http';


import { AppComponent } from './app.component';
import { TestComponent } from './components/molecules/test/test.component';


@NgModule({
  declarations: [
    AppComponent,
    TestComponent
  ],
  imports: [
    BrowserModule,
    HttpModule,
    JsonpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
12
webta.st.ic

Pour Angular 5 + uniquement les étapes de préforme 1 et 4


Afin d'accéder localement à votre fichier dans Angular 2 + , vous devez procéder comme suit (4 étapes):

[1] Dans votre dossier d'actifs, créez un fichier . Json, exemple: data.json

[2] Accédez à votre angular.cli.json (angular.json in Angular 6+) à l'intérieur de votre projet et à l'intérieur du tableau des actifs mettez un autre objet (après le package.json objet) comme ceci:

{"glob": "data.json", "input": "./", "output": "./assets/"}

exemple complet de angular.cli.json

"apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": [
        "assets",
        "favicon.ico",
        { "glob": "package.json", "input": "../", "output": "./assets/" },
        { "glob": "data.json", "input": "./", "output": "./assets/" }
      ],

Rappelez-vous, data.json est juste l'exemple de fichier que nous avons précédemment ajouté dans le dossier des ressources (vous pouvez nommer votre fichier comme vous le souhaitez)

[3] Essayez d'accéder à votre fichier via localhost. Il doit être visible dans cette adresse, http: // localhost: your_port/assets/data.json

Si ce n'est pas visible alors vous avez fait quelque chose de mal. Assurez-vous que vous pouvez y accéder en le tapant dans le champ URL de votre navigateur avant de passer à l'étape 4.

[4] Maintenant, effectuez une requête GET pour récupérer votre fichier . Json (vous avez votre chemin complet = . json URL et ça devrait être simple)

 constructor(private http: HttpClient) {}
        // Make the HTTP request:
        this.http.get('http://localhost:port/assets/data.json')
                 .subscribe(data => console.log(data));
79
Eugen Sunic

Vous devez changer

loadNavItems() {
        this.navItems = this.http.get("../data/navItems.json");
        console.log(this.navItems);
    }

for

loadNavItems() {
        this.navItems = this.http.get("../data/navItems.json")
                        .map(res => res.json())
                        .do(data => console.log(data));
                        //This is optional, you can remove the last line 
                        // if you don't want to log loaded json in 
                        // console.
    }

Car this.http.get renvoie un Observable<Response> et vous ne voulez pas de la réponse, vous voulez son contenu.

Le console.log vous montre un observable, ce qui est correct car navItems contient un Observable<Response>.

Afin d'obtenir des données correctement dans votre modèle, vous devez utiliser async pipe.

<app-nav-item-comp *ngFor="let item of navItems | async" [item]="item"></app-nav-item-comp>

Cela devrait bien fonctionner, pour plus d'informations, veuillez vous référer à documentation du client HTTP

11
Supamiu

J'ai trouvé que le moyen le plus simple pour y parvenir consiste à ajouter file.json sous le dossier : actifs.

Pas besoin de modifier:.angular-cli.json

Service

@Injectable()
export class DataService {
  getJsonData(): Promise<any[]>{
    return this.http.get<any[]>('http://localhost:4200/assets/data.json').toPromise();
  }
}

Component

private data: any[];

constructor(private dataService: DataService) {}

ngOnInit() {
    data = [];
    this.dataService.getJsonData()
      .then( result => {
        console.log('ALL Data: ', result);
        data = result;
      })
      .catch( error => {
        console.log('Error Getting Data: ', error);
      });
  }

Supplémentaire:

Idéalement, vous ne voulez avoir cela que dans un environnement de développement afin d'être à l'épreuve des balles. créer une variable sur votre environment.ts

export const environment = {
  production: false,
  baseAPIUrl: 'http://localhost:4200/assets/data.json'
};

Remplacez ensuite l'URL sur le http.get pour ${environment.baseAPIUrl}

Et le environment.prod.ts peut avoir l'URL de l'API de production.

J'espère que cela t'aides!

6
T04435

Si vous voulez mettre la réponse de la demande dans le navItems. Parce que http.get() retourne un observable, vous devrez vous y abonner.

Regardez cet exemple:

// version without map
this.http.get("../data/navItems.json")
    .subscribe((success) => {
      this.navItems = success.json();          
    });

// with map
import 'rxjs/add/operator/map'
this.http.get("../data/navItems.json")
    .map((data) => {
      return data.json();
    })
    .subscribe((success) => {
      this.navItems = success;          
    });
0
runit