webta.st.ic
Estoy tratando de cargar un archivo JSON local con http.get()
en Angular 2. Probé algo que encontré aquí en Stack Overflow. Se parece a esto:
Este es mi app.module.ts
donde import
la HttpModule
y el 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 { }
En mi componenteYO import
Http
y Response
de @angular/http
. Entonces tengo una función llamada loadNavItems()
donde trato de cargar mi contenido JSON con una ruta relativa usando http.get()
e imprimir el resultado con console.log()
. La función se llama en 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);
}
}
Mi archivo JSON local Se ve como esto:
[{
"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"
}
]
No hay ningún error en la consola, y solo obtengo este resultado:
En mi plantilla html Me gustaría hacer un bucle de los elementos de esta manera:
<app-nav-item-comp *ngFor="let item of navItems" [item]="item"></app-nav-item-comp>
Hice esto con una solución que encontré aquí en Stack Overflow, pero ¿por qué no funciona?
Editar ruta relativa:
También tengo un problema con mi ruta relativa, pero estoy seguro de que es la correcta cuando uso ../data/navItems.json
. En la captura de pantalla, se puede ver el nav-comp.component.ts archivo, donde cargo el contenido JSON usando una ruta relativa del archivo JSON que está en la carpeta llamada datos? ¿Qué ocurre? ¿La consola imprime un error 404 porque no puede encontrar mi archivo JSON desde la ruta relativa?
EugenSunic
Para Angular 5+solo realiza pasos 1 y 4
Para acceder a su archivo localmente en Angular 2+ debes hacer lo siguiente (4 pasos):
[1] Dentro de su carpeta de activos, cree un .json archivo, ejemplo: datos.json
[2] Ir a tu angular.cli.json (angular.json en Angular 6+) dentro de su proyecto y dentro del activos matriz poner otro objeto (después de la paquete.json objeto) así:
{ “glob”: “datos.json”, “entrada”: “./”, “salida”: “./activos/” }
ejemplo completo 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/" }
],
Recordar, datos.json es solo el archivo de ejemplo que agregamos previamente en la carpeta de activos (puedes nombrar tu archivo como quieras)
[3] Intente acceder a su archivo a través de localhost. Debería estar visible dentro de esta dirección, http://localhost:your_port/assets/data.json
Si es no visible entonces has hecho algo incorrectamente. Asegúrese de poder acceder a él escribiéndolo en el campo URL de su navegador antes de continuar con el paso 4.
[4] Ahora realice una solicitud GET para recuperar su .json archivo (tienes tu ruta completa .json URL y debe ser simple)
constructor(private http: HttpClient) {}
// Make the HTTP request:
this.http.get('http://localhost:port/assets/data.json')
.subscribe(data => console.log(data));
-
Hola Eugen, lo intentaré más tarde, ¡espero que funcione! Gracias
– webta.st.ic
31 de octubre de 2017 a las 8:22
-
Lo pruebo hoy y te informo.
– webta.st.ic
6 de noviembre de 2017 a las 12:11
-
@kingforever, ¿dónde te gustaría ponerlo? El archivo de activos está diseñado para tales escenarios.
– EugenSunic
24 de febrero de 2018 a las 13:26
-
En Angular 5, todo lo que necesita hacer es colocar el archivo .json en la carpeta de activos, como se menciona en el paso 1, y hacer referencia a él directamente en su llamada de servicio, como se menciona en el paso 4. A mí me funciona.
– Manoj Amalraj
13 de marzo de 2018 a las 18:07
-
Esa es una solución bastante ordenada. Gracias por la respuesta.
– Lalit Narayan Mishra
08/04/2019 a las 21:24
Supamiú
Tienes que cambiar
loadNavItems() {
this.navItems = this.http.get("../data/navItems.json");
console.log(this.navItems);
}
a
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 the loaded JSON file
// in the console.
}
Porque this.http.get
devuelve un Observable<Response>
y no quieres la respuesta, quieres su contenido.
Él console.log
muestra un observable, lo cual es correcto porque navItems contiene un Observable<Response>
.
Para obtener datos correctamente en su plantilla, debe usar un async
tubo.
<app-nav-item-comp *ngFor="let item of navItems | async" [item]="item"></app-nav-item-comp>
Esto debería funcionar bien. Para obtener más información, consulte el Documentación del cliente HTTP.
-
“El mapa de propiedades no existe en el tipo Observable
” ? – webta.st.ic
18 de mayo de 2017 a las 8:44
-
Importé “importar ‘rxjs/add/operator/map’;”, ¿el error ya no está pero la salida en la consola es la misma?
– webta.st.ic
18 de mayo de 2017 a las 8:48
-
agregar
import 'rxjs/add/operator/map';
en sus importaciones, oimport {Observable} from 'rxjs';
y cambionavItems: any
pornavItems:Observable<any>
– Supamiú
18 de mayo de 2017 a las 8:48
-
@MrBuggy si desea tener una entrada para la consola, puedo editar la respuesta para agregar una, pero pensé que su problema principal era representar el contenido en su plantilla, así que eliminé el archivo console.log.
– Supamiú
18 de mayo de 2017 a las 8:49
-
Continuemos esta discusión en el chat.
– Supamiú
18 de mayo de 2017 a las 8:58
webta.st.ic
mi propia solucion
Creé un nuevo component
llamó test
en esta carpeta:
También creé un simulacro llamado test.json
en el assets
carpeta creada por angular cli
(importante):
Este simulacro se ve así:
[
{
"id": 1,
"name": "Item 1"
},
{
"id": 2,
"name": "Item 2"
},
{
"id": 3,
"name": "Item 3"
}
]
En el controlador de mi componente test
, import
seguir rxjs
Me gusta esto:
import 'rxjs/add/operator/map'
Esto es importante, porque tienes que map
su response
del HTTP CONSEGUIR llamada, por lo que obtiene contenido JSON y puede reproducirlo en su ngFor
. Aquí está mi código de cómo cargo los datos simulados. solía http
get
y llamó mi camino al simulacro con este camino this.http.get("/assets/mock/test/test.json")
. Después de esto yo map
la respuesta y subscribe
eso. Luego lo asigno a mi variable. items
y bucle con ngFor
en mi template
. También exporto el tipo. Aquí está todo el código de mi controlador:
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);
});
}
}
Y mi bucle en su template
:
<div *ngFor="let item of items">
{{item.name}}
</div>
¡Funciona como se esperaba! Ahora puedo agregar más archivos simulados en la carpeta de activos y simplemente cambiar la ruta para obtenerlo como json
. Tenga en cuenta que también tiene que importar el HTTP
y Response
en su controlador. Lo mismo en tu app.module.ts (principal) así:
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 { }
-
.map(data => data.json() as Array
- ) Esta línea me dice que Object no tiene el método ‘json’
– Corrió Lottem
1 de marzo de 2018 a las 0:15
-
@RanLottem ¿Exporta el tipo “Artículo” correctamente?
– webta.st.ic
1 de marzo de 2018 a las 9:14
-
Independientemente del tipo que agregue en esta línea, data.json() todavía da un error de que ‘Objeto’ no tiene una propiedad json.
– Corrió Lottem
1 de marzo de 2018 a las 11:31
-
la obtención predeterminada devuelve json, no es necesario hacer .json()
– Sam Vloeberghs
24 de febrero de 2019 a las 20:23
T04435
Descubrí que el más simple manera de lograr esto es agregando el archivo.json archivo debajo de la carpeta activos.
no hay alguna necesito editar el archivo .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);
});
}
###Extra:
Idealmente, solo desea tener esto en un entorno de desarrollo, por lo que para ser infalible, cree una variable en su medio ambiente.ts expediente:
export const environment = {
production: false,
baseAPIUrl: 'http://localhost:4200/assets/data.json'
};
Luego reemplace la URL en el http.get por ${environment.baseAPIUrl}
.
Y el medio ambiente.prod.ts El archivo puede tener la URL de la API de producción.
Felipe Owino
Ponga su elementos de navegación.json archivo en la carpeta “activos”. Angular sabe cómo mirar dentro de la carpeta de activos. Así que en lugar de:
loadNavItems() {
this.navItems = this.http.get("../data/navItems.json");
console.log(this.navItems);
}
Cambie la ruta a simplemente:
loadNavItems() {
this.navItems = this.http.get("assets/navItems.json");
console.log(this.navItems);
}
-
Gracias Philip por tu calmado consejo… me ayudó 🙂
–Kieran Ryan
19 oct 2021 a las 18:26
Pedro Mortensen
-
crear/mover el archivo JSON en la carpeta
assets
-
implementar un método en el servicio
private URL = './assets/navItems.json'; // ./ is important! constructor(private httpClient: HttpClient) { } fetch(): Observable<any> { return this.httpClient.get(this.URL); }
-
llamarlo en componente
private navItems: NavItems[]; constructor(private navItemsService: NavItemsService) { } ngOnInit(): void { this.publicationService.fetch().subscribe(navItems => this.navItems = navItems); }
-
Gracias Philip por tu calmado consejo… me ayudó 🙂
–Kieran Ryan
19 oct 2021 a las 18:26
Pedro Mortensen
Si desea poner la respuesta de la solicitud en el navItems
. Porque http.get()
devuelve un observable, tendrás que suscribirte a él.
Mira este ejemplo:
// 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;
});
-
Esta es otra forma de resolver el problema. Sí, principalmente uso tubería asíncrona para evitar el uso de variables solo para almacenar resultados. Además, la canalización asíncrona es mejor para mí porque cancelará la suscripción por usted, lo que significa que evitará pérdidas de memoria si tiene elementos observables que persisten en las páginas (servicios, por ejemplo).
– Supamiú
18 de mayo de 2017 a las 8:57
-
Estoy de acuerdo. Es una forma más fácil de resolver y comprender el problema, pero al final usaré tu solución.
– ejecutarlo
18 de mayo de 2017 a las 9:10
-
Encontré mi propia solución y la publiqué a continuación (marcada como respuesta correcta). Gracias de nuevo.
– webta.st.ic
16 de enero de 2018 a las 15:27
Encontré mi propia solución y la publiqué a continuación (marcada como respuesta correcta). Gracias de nuevo.
– webta.st.ic
16 de enero de 2018 a las 15:26
Tengo un problema similar, pero un poco diferente. Tengo una imagen en la carpeta de activos. Y tengo una propiedad de tipo
File
en mi servicio Quiero leer esa imagen en mis activos en unFile
escriba Object. ¿Puede ayudar a lograr esto?– Himanshu Mittal
13/09/2021 a las 17:04