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 import
Http
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:
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?
MA PROPRE SOLUTION
J'ai créé un nouveau component
appelé test
dans ce dossier:
J'ai également créé une maquette appelée test.json
Dans le dossier assests
créé par angular cli
(Important):
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 test
import
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é http
get
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 { }
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));
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
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);
});
}
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!
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;
});