Load json dynamically in Angular 8
Asked Answered
P

5

7

So I have to load a value from a configuration json file in my Angular 8 app.

In the beginning I was loading it statically and so when the js was minified - the unset value from the json was read once and never again.

Then I tried to load it dynamically like so:

app.component.ts:

ngOnInit(): void {
    let appInfo = "";
    import("../assets/config/config.json").then(config => {
       appInfo = config.appInfo;
    });
    //using appInfo here - empty string.
}

Well that didn't work out either. Again it was unset. But it is actually present in my config.json..

Anyone have an idea on another approach I can try?

Edit: I want to access this on ngOnInit of my app.component.ts. My case is that before app startup someone will update the appInfo value in the config.json. I want to access it at startup. Also thank you all for the suggestions, I will try them out and update which ones work.

**** EDIT: None of the dynamic loading techniques worked for me. I ended up doing it with a http call although I tried all possible to avoid it.

Pendulous answered 10/4, 2020 at 6:24 Comment(8)
Use httpClient get to fetch json.Interior
I can't do that. I don't have direct access..Pendulous
Have you tried using import jsonconfig from "../assets/config/config.json"; and then configuring your tsconfig.json with these two "resolveJsonModule": true, "esModuleInterop": true,Sandiesandifer
@Ashwyn yes, this is what I mean by statically importing. It imported it when minifying the js..Pendulous
Why dynammically? Do you change the json at some point?Brande
Yes, I do and it is for sure before the angular app startup.Pendulous
In which event do you want to laod json data dynamically ? can you elaborate your use-case?Soyuz
@GaurangDhorda I want to load in on ngOnInit of my app.component.ts, or otherwise said in the earliest possible moment of my application startup. This value will be written sometime before the app startup but after the js is minified - so that's why static imports don't work for me. I updated the description with some more details. Thanks.Pendulous
C
3
 ngOnInit(): void {
    let appInfo = "";
    this.getDataHttp('../assets/config/config.json').subscribe(
      data => {
        var testResponse = data;
        console.log("I CANT SEE DATA HERE: ", testResponse);
      }
  )
}

get call for file, file can be any ware in other server or local

getDataHttp(url:string) {

    return this.http.get(url);
}

subscription of that call

OR

you can also apply es 2020 dynamic import natively

var  moduleSpecifier = '../assets/config/config.json'
  import(moduleSpecifier).then((data) => {       
     let temp=data
    }).catch(error =>{debugger;alert(error.message)});
Contort answered 10/4, 2020 at 12:28 Comment(0)
S
0

I just tried a require solution by installing @types/node with command npm i --save-dev @types/node

then added this to tsconfig.app.json

"compilerOptions": {
    "outDir": "./out-tsc/app",
    "types": ["googlemaps", "node"]
  }

then had console.log(require("../assets/config/config.json")); somewhere where it would get called

then restarted with ng serve, and it worked...

Sandiesandifer answered 10/4, 2020 at 6:57 Comment(1)
I just tested this on an app i have here and it worked...can you give it go and see please...Sandiesandifer
E
0

Give one more approach to achieve same as answer of @jadli with different approach.

appConfig.ts

export interface AppConfig {
    BaseApi: string;
}

Create interface which handle value of dynamic json file response.

config-loader.service.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { AppConfig } from '@core/models/appConfig';
import { tap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})

export class ConfigLoaderService {
  constructor(private httpClient: HttpClient) { }

  public BaseApi: string = "";
  public initialize() {
    return this.httpClient
      .get<AppConfig>('../../../assets/AppSettings/appsettings.json')
      .pipe(
        tap((response: AppConfig) => {
          this.BaseApi = response.BaseApi;
        })
    );
  }
}

Create service which is responsible for getting data from json file. To demonstrate type safe i have take interface to get response data.

preload-factory.ts

import { ConfigLoaderService } from '@core/services/config-loader.service';
export function PreloadFactory(configService: ConfigLoaderService) {
  return () => configService.initialize();
}

create factory which is responsible for initialize config loader initialize method.

app.module.ts

providers: [
    ConfigLoaderService,
    {
      provide: APP_INITIALIZER,
      deps: [
        ConfigLoaderService
      ],
      multi: true,
      useFactory: PreloadFactory   // use factory to inject service at initialize
    }
],

in my example I have created one folder under -- assets/Appsettings from where try to reading json data.

appsetting.json
Eby answered 14/7, 2023 at 13:49 Comment(0)
I
-1

in your component import it like this.

import * as jsonData from '../assets/test.json';

then

ngOnInit() {
  console.log(jsonData)
}

I am able to fetch data like this.

Updated

Dynamic Loading

  private jsonData;

  async ngOnInit() {
    await import("../assets/test.json").then(data => {
      this.jsonData = data;
    });

    console.log(this.jsonData);
  }

Working Demo

Interior answered 10/4, 2020 at 6:41 Comment(3)
Thank you for the answer. I should have given this example when I was talking about static loading. Sadly this is static loading. I need a way to dynamically do that...Pendulous
I have updated code, please check now. Added working demo link as well.Interior
Thank you for the update, I will try this out and update if it worked for me as well.Pendulous
S
-1

Working Demo in this StackBlitz Live Demo

  • You can leverage use of rxjs in angular. Here, first of all we can get reference of json file in assets folder using import().
  • fromPromise() operator is converting our import json file promise into the observable. so that in future if anything is changed from json file we can get changed value at the same time [ Live Update To Template HTML file].
  • We use async pipe for subscribing observable and un-subscribing observable automatically by angular.

EDIT

app.component.ts is

  import {Observable} from 'rxjs';
  import { fromPromise } from 'rxjs/internal-compatibility';


  export class AppComponent  {
     dataJson: Observable<unknown>;
     dynamicallyLoadJsonFile = import('../assets/data.json');
     
     ngOnInit(){
         this.dataJson = fromPromise(this.dynamicallyLoadJsonFile);
     }
  }

app.component.html is

<ng-container *ngIf="dataJson | async as data">
    <table class="table table-striped table-dark">
       <thead>
           <tr>
               <th scope="col">Id</th>
               <th scope="col">Name</th>
           </tr>
       </thead>
       <tbody>
           <tr *ngFor="let row of data['default'] ; let i=index">
               <td> {{row.id }} </td>
               <td> {{row.CarName}}</td>
           </tr>
       </tbody>
    </table>
</ng-container>

Now, after update value in your json file form assets folder all changes are automatically reflected in template file without having to re-write it again..

Soyuz answered 10/4, 2020 at 11:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.