Загрузите json из локального файла с помощью http.get() в угловом 2
Я пытаюсь загрузить локальный json с http.get()
в угловом 2. Я попробовал что-то, что я нашел здесь в стеке. Это выглядит так:
это мой app.module.ts
где я import
HttpModule
и JsonModule
из @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 { }
В моем компоненте я import
Http
и Response
из @angular/http
. Тогда у меня есть функция loadNavItems()
, где я пытаюсь загрузить мой json с относительным путем с помощью http.get()
и распечатать результат с помощью console.log()
. Функция вызывается в 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);
}
}
Мой локальный файл json выглядит так:
[{
"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"
}
]
В консоли нет ошибок, я просто получаю этот вывод:
В моем html-шаблоне я хотел бы создать такие элементы:
<app-nav-item-comp *ngFor="let item of navItems" [item]="item"></app-nav-item-comp>
Я сделал это с решением, которое я нашел здесь в стеке, но я понятия не имею, почему он не работает?
РЕДАКТИВАЙТЕ ОТНОСИТЕЛЬНУЮ ПУТЬ: У меня также возникает проблема с моим относительным путем, но я уверен, что это правильно, когда я использую ../data/navItems.json
. На скриншоте вы можете найти nav-comp.component.ts, где я загружаю json, используя относительный путь из json файла, который находится в папке с именем data? Что не так, консоль печатает ошибку 404, потому что она не может найти мой json файл из относительного пути?
Ответы
Ответ 1
МОЕ СОБСТВЕННОЕ РЕШЕНИЕ
Я создал новый component
под названием test
в этой папке:
Я также создал mock под названием test.json
в папке assests
созданной angular cli
(важно):
Этот макет выглядит следующим образом:
[
{
"id": 1,
"name": "Item 1"
},
{
"id": 2,
"name": "Item 2"
},
{
"id": 3,
"name": "Item 3"
}
]
В контроллере моего test
компонента import
следуют rxjs
как это
import 'rxjs/add/operator/map'
Это важно, потому что вам нужно map
свой response
с вызовом http get
, поэтому вы получаете json
и можете зацикливать его в ngFor
. Вот мой код, как я загружаю макет данных. Я использовал http
get
и назвал свой путь к макету с этим путем this.http.get("/assets/mock/test/test.json")
. После этого я map
ответ и subscribe
. Затем я назначаю его своим переменным items
и зацикливаю его на ngFor
в моем template
. Я также экспортирую тип. Вот мой весь код контроллера:
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);
});
}
}
И моя петля в этом template
:
<div *ngFor="let item of items">
{{item.name}}
</div>
Он работает так, как ожидалось! Теперь я могу добавить больше файлов-макетов в папку assests и просто изменить путь, чтобы получить его как json
. Обратите внимание, что вы также должны импортировать HTTP
и Response
в свой контроллер. То же самое в вас app.module.ts(main):
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 { }
Ответ 2
Для angular 5+ только предварительных этапов 1 и 4
Для локального доступа к вашему файлу в Angular 2+ вам необходимо выполнить следующие действия (4 шага):
[1] Внутри вашей папки ресурсов создайте файл .json, пример: data.json
[2] Перейдите к вашему angular.cli.json(angular.json в Angular 6+) внутри вашего проекта и внутри массива assets, поместите другой объект (после объекта package.json), например это:
{"glob": "data.json", "input": "./", "output": "./assets/"}
полный пример из angular.cli.json
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico",
{ "glob": "package.json", "input": "../", "output": "./assets/" },
{ "glob": "data.json", "input": "./", "output": "./assets/" }
],
Помните, data.json - это просто пример файла, который мы ранее добавили в папку ресурсов (вы можете назвать свой файл как хотите)
[3] Попробуйте получить доступ к вашему файлу через localhost. Он должен быть виден по этому адресу, http://localhost: your_port/assets/data.json
Если он не виден, значит, вы что-то сделали неправильно. Убедитесь, что вы можете получить к нему доступ, введя его в поле URL в браузере, прежде чем перейти к шагу # 4.
[4] Теперь выполните запрос GET, чтобы получить файл .json (у вас есть полный путь .json URL, и он должен быть простым)
constructor(private http: HttpClient) {}
// Make the HTTP request:
this.http.get('http://localhost:port/assets/data.json')
.subscribe(data => console.log(data));
Ответ 3
Вы должны изменить
loadNavItems() {
this.navItems = this.http.get("../data/navItems.json");
console.log(this.navItems);
}
для
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.
}
Поскольку this.http.get
возвращает Observable<Response>
и вы не хотите ответа, вы хотите его содержимое.
console.log
показывает вам наблюдаемое, что верно, потому что navItems содержит Observable<Response>
.
Чтобы правильно получить данные в вашем шаблоне, вы должны использовать async
канал.
<app-nav-item-comp *ngFor="let item of navItems | async" [item]="item"></app-nav-item-comp>
Это должно работать хорошо, для получения дополнительной информации обратитесь к документации HTTP Client
Ответ 4
Я обнаружил, что самый простой способ добиться этого - добавить файл.json в папку: assets.
Нет необходимости редактировать: .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);
});
}
Дополнительно:
В идеале вы хотите, чтобы это было в среде разработчиков, чтобы быть пуленепробиваемым. создать переменную на вашей environment.ts
export const environment = {
production: false,
baseAPIUrl: 'http://localhost:4200/assets/data.json'
};
Затем замените URL-адрес http.get на ${environment.baseAPIUrl}
И environment.prod.ts
может иметь URL-адрес API для создания.
Надеюсь это поможет!
Ответ 5
Я хочу отправить ответ запроса в navItems
. Поскольку http.get()
возвращает наблюдаемый, вам придется подписаться на него.
Посмотрите на этот пример:
// 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;
});
Ответ 6
Если вы используете Angular CLI: 7.3.3
, я сделал следующее: в папке "Мои активы" я разместил свои поддельные данные json, а затем на своих сервисах я только что сделал это.
const API_URL = './assets/data/db.json';
getAllPassengers(): Observable<PassengersInt[]> {
return this.http.get<PassengersInt[]>(API_URL);
}
Ответ 7
try: this.navItems = this.http.get("data/navItems.json");