Загрузите 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"
    }
]

В консоли нет ошибок, я просто получаю этот вывод: enter image description here

В моем 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 файл из относительного пути?

enter image description here

Ответ 1

МОЕ СОБСТВЕННОЕ РЕШЕНИЕ

Я создал новый component под названием test в этой папке:

enter image description here

Я также создал mock под названием test.json в папке assests созданной angular cli (важно):

enter image description here

Этот макет выглядит следующим образом:

[
        {
            "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);
  }

enter image description here

Ответ 7

try: this.navItems = this.http.get("data/navItems.json");