Challenges with incorporating asynchronously fetched data in component operations

I have encountered an issue where the data retrieved from a server in a service is available in the component's template but not in the actual code. This seems strange to me.

I made the call in the ngOnInit method of my main AppComponent

ngOnInit() { 
    this.dataContractService.getUIStrings();
}

This method is called before any other component's ngOnInit, so the strings should be available to them.

Here is the code for getUIStrings:

async getUIStrings() {
    let url = "/datacontract/getuistrings";
    let promise = await this.http.get<APIResponse>(url).pipe(map(x => { return x.responsePayload })).toPromise<any>();
    this.globals.UIStrings = promise.strings; //
}

The results are stored in globals, which is an injectable service used by components that need access to UIStrings.

Here is an example of how I am using it:

export class DashboardComponent {

    constructor(
        public globals: Globals,
    ) { }

    dashboardMessage: string;

    ngOnInit() {
        if (condition) {
            this.dashboardMessage = this.globals.UIStrings["DashboardAdminDesc"];
        }
        else {
            this.dashboardMessage = this.globals.UIStrings["DashboardDesc"];
        }

    }

}

In the code, UIStrings is an empty array, but in the component's template above, it is available and populated.

{{globals.UIStrings["DashboardAdminDesc"]}}

This setup seems to work. Can anyone point out what I might be doing wrong here?

Answer №1

There are a few issues that need to be addressed:

  1. Initially, the ngOnInit function of the appcomponent will be called, triggering the execution of the getUIStrings function. This function returns a promise which takes approximately 5 minutes to resolve, and once resolved, it assigns the result to this.globals.UIStrings.

  2. During this period when the promise is still unresolved, the DashboardComponent loads and as a result, this.dashboardMessage remains undefined because this.globals.UIStrings does not contain any data yet.

  3. In the HTML code, using

    {{globals.UIStrings["DashboardAdminDesc"]}}
    will work eventually as the data will be available once the promise is resolved. The reference to this.globals in HTML means that any changes made to it from a service will reflect directly in the HTML where it's used, but not in the .ts file.

    However, using {{this.dashboardMessege}} will always return undefined since the ngOnInit of the dashboard is executed before the promise is resolved.


Solution

I'm providing some suggestions without testing the code. Please adjust accordingly based on your requirements. I have not altered this.globals.UIStrings in the code snippet below.

NOTE: This solution is necessary due to the asynchronous nature of the app & dashboard components.

global.service

  response = new Subject<any>();  // consider response as your globals.UIStrings

async getUIStrings() {
    let url = "/datacontract/getuistrings";
    let promise = await this.http.get<APIResponse>(url).pipe(map(x => { return x.responsePayload })).toPromise<any>();
            
    this.response.next(promise.strings);                      // emitted data available here
}

Dashboard.component.ts

export class DashboardComponent {
    dashboardMessage: string;

    constructor(public globals: Globals) { 
              
               this.globals.response.subscribe(data=>{     // received data here

                  if (condition) {
                     this.dashboardMessage = data["DashboardAdminDesc"];
                  }
                  else {
                     this.dashboardMessage = data["DashboardDesc"];
                  }
                  
               })
     }
}

.html

{{dashboardMessge}} will consistently display desired result 
          

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

Helping React and MUI components become mobile responsive - Seeking guidance to make it happen

My React component uses Material-UI (MUI) and I'm working on making it mobile responsive. Here's how it looks currently: https://i.sstatic.net/kxsSD.png But this is the look I want to achieve: https://i.sstatic.net/kJC2m.png Below is the code ...

Stop Angular (click) binding from occurring when the variable is considered 'undefined'

Currently, I am enhancing a custom Angular component by adding callbacks using the standard Angular method, like so: (click)="data.callback ? data.callback() : undefined" This approach works smoothly; when no callback is specified, Angular handl ...

Is it possible to create cloud functions for Firebase using both JavaScript and TypeScript?

For my Firebase project, I have successfully deployed around 4 or 5 functions using JavaScript. However, I now wish to incorporate async-await into 2 of these functions. As such, I am considering converting these specific functions to TypeScript. My conc ...

Utilizing a single Angular 2 app to incorporate various components on a single page

Can you guide me on how to dynamically render a section of HTML from a child component to a parent component in Angular 2? The concept is to create a main layout where different sections can be replaced or customized by child components based on specific r ...

Conceal the Froala editor when blur events occur

Currently, I am utilizing Forala with the specific setting: initOnClick: true, Everything is running smoothly, but is there a way to accomplish the "opposite" I'm looking to hide the editor upon blur? I have searched through the documentation, but d ...

Show pictures stored in S3

I currently have an Amazon AWS S3 Bucket where I store images. Each object in the bucket has its own link, but when I try to open it in a browser, the image downloads instead of displaying directly on the site. This makes it challenging to view the images ...

Issue with deep linking functionality on S3 storage service turning out to be

After successfully deploying my angular5 app to: http://myApp.s3domain.amazonaws.com The Angular router is automatically directing me to http://myApp.s3domain.amazonaws.com/home However, when I try to access a link with a unique parameter like so: http:/ ...

How to activate form autofill in an Angular app

After migrating my app to Angular, I noticed that the form no longer autocompletes upon returning page visits. However, everything else seems to be working perfectly fine. I have a hunch that this issue is related to the *ngIf template expressions and the ...

Schedule - the information list is not visible on the calendar

I am trying to create a timeline that loads all data and events from a datasource. I have been using a dev extreme component for this purpose, but unfortunately, the events are not displaying on the calendar. Can anyone offer any insights into what I might ...

I'm having trouble importing sqlite3 and knex-js into my Electron React application

Whenever I try to import sqlite3 to test my database connection, I encounter an error. Upon inspecting the development tools, I came across the following error message: Uncaught ReferenceError: require is not defined at Object.path (external "path ...

Utilizing i18next for both a custom Typescript library and a host simultaneously: a step-by-step guide

Currently, I am in the process of developing a typescript library that is designed to take in an object and generate an excel file. This library is intended for use with multiple React applications. Each React application, or host, will provide its own obj ...

Issues have been encountered with Angular 5 when trying to make required form fields work properly

Just created my first Angular app using Angular 5! Currently following the documentation at: https://angular.io/guide/form-validation. Below is the form I have set up: <form class="form-container"> <mat-form-field> <input matInput pl ...

The Ionic framework is encountering difficulties in resolving all parameters for the service

I have created an IncomeTempService: import {incomeService} from "./income.service"; export class incomeTempService { private incomeTmp: {value: number, usage: string, date: string}; private value = null; private usage = null; constructor(priva ...

Update dynamically generated CSS automatically

Is there a way to dynamically change the CSS? The problem I'm facing is that the CSS is generated by the framework itself, making it impossible for me to declare or modify it. Here's the scenario at runtime: I am looking to target the swiper-pa ...

When attempting to assign a 'string' type to the @Input property, I am receiving an error stating that it is not assignable to the 'PostCard Layout' type

Encountering an issue The error message 'Type 'string' is not assignable to type 'PostCard Layout'' is being displayed A parent component named page-blog.component.html is responsible for defining the class styles and passi ...

Firebase initialization unsuccessful due to incorrect directory placement

I've been encountering an issue while deploying my Angular 2 project to Firebase. The initial deployment was successful, but subsequent attempts only show the Firebase Hosting welcome page instead of my project in the URL. I've realized that even ...

A guide on capturing the text content of the error message from the <mat-error> element with Protractor

I have encountered an element that is giving me trouble in retrieving the error message text into a variable. <mat-error _ngcontent-c16="" class="mat-error ng-star-inserted" id="error-email-required" role="alert" ...

Troubleshooting issues when integrating three.js GLTFLoader() with TypeScript due to conflicts with zimjs

Successfully loading a model using three.js GLTFLoader() with TypeScript in a nuxt.js application: this.mGLTFLoader = new (<any>THREE).GLTFLoader(); this.mGLTFLoader.load(pPath, (gltf) => this.onLoad(gltf), (xhr) => this.onProgress(xhr), (e) = ...

Verify the ability to view a webpage

I am currently working on creating a method to check if data access is equal to next.data.access. Since it's an array, I cannot use the includes method. It would be enough for just one of the data access values in the array to return true. auth.guard ...

The parameter of type 'never' cannot be assigned with the argument of type 'number | boolean | undefined'

In my project, I am creating a validation input using TypeScript in Next.js. interface InputRules { required?: boolean min?: number max?: number minLength?: number maxLength?: number } I have defined an object that contains methods to handle val ...