Service in Angular2 designed to retrieve JSON data and extract specific properties or nodes from the JSON object

Currently, I am trying to teach myself Angular2 and facing some difficulties along the way. I am working on creating a service that loads a static JSON file. Right now, I am using i18n files as they are structured in JSON format. The service will include a method that takes a parameter and searches for the corresponding JSON property. It may sound straightforward, but I have a few questions. Here is the service I created called ContentService, which is saved in the file content.service.ts

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http'

@Injectable()
export class ContentService {

    loadedContent: any; // will assign a proper type later

    constructor(private http: Http) {

        // 1. Determine the language
        let userLang:string = navigator.language.split('-')[0];
        userLang = /(en|de)/gi.test(userLang) ? userLang : 'en';

        // 2. Load the file... should consider using interpolation for the file path
         this.http.get('src/i18n/' + userLang + '.json').map((res:Response) => res.json()).subscribe(res => this.loadedContent = res);
    }

    getContent(selector) {

        // need to fetch content from the loaded JSON based on the selector passed, for now just returning the passed selector 
        console.log(selector, this.loadedContent); // this.loadedContent is undefined!
        // need to handle case when the selector is not found....
    }
}

In another component, I import the service...

import { ContentService } from '../content/content.service';

@Component({
    selector: 'angular2-test',
    providers: [ ContentService ],
    templateUrl: 'src/home/home.template.html'
})

export class TestComponent {

    content: any; // real type will be added later

    constructor(private contentService: ContentService) {
        this.content = this.contentService.getContent('promotion')
    }
}

I am encountering an error where my getContent method does not have access to this.loadedContent and returns "undefined" in the console. How can I ensure that my method can access the loadedContent property of the service?

By the way, here is the content of my static JSON file that successfully loads in the service...

{
  "promotion": {
    "pageTitle": "Oh we have a lovely promotion today..."
  }
}

Thank you in advance!

Answer №1

To enhance your service, consider transitioning it to an asynchronous model:

import {Observable} from 'rxjs/Rx';

@Injectable()
export class ContentService {
  loadedContent: any; // specific type to be defined later
  obs: Observable<any>;

  constructor(private http: Http) {
    let userLang:string = navigator.language.split('-')[ 0 ];
    userLang = /(en|de)/gi.test(userLang) ? userLang : 'en';

    this.obs = this.http.get('src/i18n/' + userLang + '.json')
      .map((res:Response) => res.json())
      .do(res => this.loadedContent = res);
  }

  getContent(selector) {
    if (this.loadedContent) {
      return Observable.of(this.loadedContent);
    } else {
      return this.obs;
    }
  }
}

You can utilize the above code in your component like this:

@Component({
  selector: 'angular2-test',
  providers: [ ContentService ],
  templateUrl: 'src/home/home.template.html'
})
export class TestComponent {
  content: any; // actual type will be determined later

  constructor(private contentService: ContentService) {
    this.contentService.getContent('promotion').subscribe(content => {
      this.content = content;
    });
  }
}

An alternative approach could involve bootstrapping your application asynchronously. For more information on this, refer to the following question:

  • How to defer Main component's initialization of dependent components so that some promises may get resolved

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Dynamic content updating for FAB lists in Ionic 4

I'm currently diving into Ionic 4 and facing an issue with dynamically updating the contents of a fab list when it's opened. My goal is to have a selection trigger a display of buttons that will evolve over time. For example, the function srv.ge ...

Absence of "Go to Definition" option in the VSCode menu

I'm currently working on a Typescript/Javascript project in VSCODE. Previously, I could hover my mouse over a method to see its function definition and use `cmd + click` to go to the definition. However, for some unknown reason, the "Go to Definition" ...

Encountered an issue with ionViewDidLoad: The property 'firstChild' cannot be read as it is null

While working on an Ionic 2 App with Angular2 and Typescript, I encountered an issue when trying to pass a JSON to map for markers. Here is the link to the gist containing the code snippet I am facing an error that reads: view-controller.js:231 MapPage i ...

Angular MDBootstrap formatting disappears upon refresh of the page

I am currently utilizing the MDBootstrap package for Angular in my project, specifically focusing on styling buttons within a page I am developing. Upon initial loading of the page, the button styles are successfully applied. However, upon reloading the p ...

Encountering issues in transmitting form data to a Node server from Angular

In my Angular application, I am working on creating a registration page with validation. Once the user fills out the form and submits it, the data is sent to the server and saved in MongoDB. This is the approach I have taken: register_user() { const ...

Using Dynamic Imports in Angular 6 Libraries

After creating a sample Angular 6 Library using the Angular CLI, I have the basic structure with the library "my-lib" and the sample app "test-lib" for testing purposes. Within the library, I am looking to implement dynamic imports. Specifically, I have a ...

Mastering Angular: Accessing undefined properties (specifically 'push')

Currently, I am in the process of learning Angular and have encountered an issue while working on an assignment. The error message that I am facing is "Cannot read properties of undefined (reading 'push')." Despite knowing that this is a common e ...

Need help with resetting a value in an array when a button is clicked?

Using Tabulator to create a table, where clicking on a cell pushes the cell values to an array with initial value of '0'. The goal is to add a reset button that sets the values back to '0' when clicked. component.ts names = [{name: f ...

Exploring the integration of an Angular 4 application with Visual Studio 2017 using dot net core. Techniques for accessing configuration keys from appsetting.json in a TypeScript

I'm currently working on an Angular 4 application using Visual Studio 2017 with .NET Core. I need to figure out how to access configuration keys from appsetting.json in my TypeScript file. I know how to do it in the startup.cs file, but I'm strug ...

angular material drag and drop triggers a callback once the css transition has completed

I have successfully implemented a list of elements that can be dragged and dropped using Angular Material's drag and drop feature, similar to the tutorial available at this link. In my implementation, I have a "drop(event)" function that not only mov ...

Issues with getOptionLabel in Material UI

I have a constant with the following values : const Reference = [ { label: "RF-100", year: "Test" }, { label: "RF-200", year: "Test2" }, { label: "RF-300", year: "Test3" }, ]; and my Autoco ...

Troubleshooting the inclusion of nodemon in package.json

I am interested in implementing nodemon to automatically recompile the project when there are changes made to the code during development. package.json { "name": "insurance-web-site", "version": "0.1.0", " ...

Vue defineProps allows for the definition of complex types for properties

Within my code, I am exploring the use of complex prop types in certain instances. Below is an example of what I have in mind: enum Country { [...] } interface IPerson { firstname: string; lastname: string; } interface IAddress { street: string; ...

What is the reason behind the ability to reassign an incompatible function to another in TypeScript?

I discovered this question while using the following guide: https://basarat.gitbooks.io/typescript/content/docs/types/type-compatibility.html#types-of-arguments. Here is an example snippet of code: /** Type Heirarchy */ interface Point2D { x: number; y: ...

Having difficulties running the updated project from Angular 4 to 6

I recently updated my Angular 4 project to Angular 6. While trying to run the project, I encountered an error. Despite searching for similar questions, I was unable to find a satisfactory answer. OpaqueToken is not a constructor. Below is a snippet ...

The input type "number" does not seem to be compatible with the currency pipe feature

The currency pipe seems to not be working when using the input type number. The web page is not displaying any value. I have searched various blogs and it appears that the currency pipe only works with input type text, but my requirement necessitates the ...

Using the ternary operator in React to implement inline styles

Within my React/Typescript project, I aim to dynamically exhibit a color based on the presence or absence of a value in payload[1]. In the code snippet below, note the usage of an inline style tag. <li className="recharts-tooltip-item" style={ ...

Any tips on how to personalize the loading animation for single pages using CSS and GIFs?

presentLoading(message) { this.loading = this.loadingCtrl.create({ dismissOnPageChange: false, spinner:'hide', content:`<img class="load" src="assets/dual.gif" />`, }); this.loading.present(); } Hello there! I am working with the ...

How can I redirect a page using an axios interceptor in Next.js?

Is there a way to redirect the page in an axios interceptor when dealing with server-side rendering limitations? Unfortunately, I am unable to access the server side context in the axios interceptor. I have tried using next/router but it only works on the ...

Create a debounce click directive for buttons in a TypeScript file

I'm facing an issue with implementing debounce click on a dynamically added button using TypeScript. I need help with the correct syntax to make it work. private _initActionsFooter(): void { this.actionsFooterService.add([ { ...