I'm curious, in TypeScript, how can I access a class variable from within a method

I've hit a roadblock and can't seem to figure it out. Despite scouring the forum and tirelessly searching on Google for hours, I'm unable to solve this issue! This is my first attempt at creating an app with Angular, and it's safe to say that I am struggling.

The problem lies with a class variable called stats4Graphs which I receive from a service in .net core 3.1. While I can successfully display the data in the html section of the component using

stats4Graph<code>, I encounter difficulties when trying to utilize the variable within the function that calls the service. Even a simple statement like <code>console.log('Labels in: ' + this.stats4Graphs.label);
returns "Labels in: undefined" in the console. I'm completely stuck and don't know how to proceed.

Here is the model definition for stats4Graphs:

export class Stats4Graphs {
    axisLabels: string[] = [];
    label: string;
    points: number[] = [];
}

I'm unsure if I need to initialize the arrays here or not; it was one of my last-ditch efforts to resolve the issue.

Below is the code snippet from my component.ts file:

import { Component, OnInit } from '@angular/core';
import { Stats4Graphs } from 'src/app/shared/models/stats4-graphs.model';
import { ProfileService } from '../profile.service';

@Component({
  selector: 'app-engagement-chart',
  templateUrl: './engagement-chart.component.html',
  styleUrls: ['./engagement-chart.component.css']
})
export class EngagementChartComponent implements OnInit {  

  public stats4Graphs: Stats4Graphs = new Stats4Graphs();

  // ADD CHART OPTIONS. 
  chartOptions = {
    responsive: true    // THIS WILL MAKE THE CHART RESPONSIVE (VISIBLE IN ANY DEVICE).
  }

  labels =  [];

  // STATIC DATA FOR THE CHART IN JSON FORMAT.
  chartData = [
    {
      label: '',
      data: [] 
    }
  ];

  // CHART COLOR.
  colors = [
    { // 1st Year.
      backgroundColor: 'rgba(77,83,96,0)',
      borderColor: 'rgba(77,83,96,0.2)',
      borderWidth : 2
    }
  ]

  // CHART CLICK EVENT.
  onChartClick(event) {
    console.log(event);
  }
  constructor(private profileService: ProfileService) { }

  ngOnInit() {
    this.profileService.getEngagement('UC__8h96Jwsaptaqh227Q9gg')
    .subscribe(stats4Graphs => {
      this.stats4Graphs = stats4Graphs;
    });
  
    console.log('Labels in engagement: ' + this.stats4Graphs.label);
    this.labels = this.stats4Graphs.axisLabels as any;
  }

}

In essence, I am attempting to create a line chart using Chart.js and ng2-charts to showcase the data within stats4Graphs. However, I'm clueless about how to populate chartData with the information from stats4Graphs.points and stats4Graphs.label. Any guidance regarding this would be greatly appreciated.

Despite my struggle, I can confirm that the service does work because I'm able to display the values retrieved from the service in the component.html file.

<p>{{ stats4Graphs.label }}
        <br />
        {{ stats4Graphs.axisLabels }}
        <br />
        {{ stats4Graphs.points }}
    </p>

Thank you for your anticipated assistance!

Answer №1

When you see the output 'Labels in: ' + this.stats4Graphs.label, it shows <code>undefined
because the function call to
this.profileService.getEngagement('UC__8h96Jwsaptaqh227Q9gg')
is asynchronous and has not finished yet.

To fix this, make sure to place the code inside the subscribe block:

this.profileService.getEngagement('UC__8h96Jwsaptaqh227Q9gg')
  .subscribe(stats4Graphs => {
    this.stats4Graphs = stats4Graphs;

    console.log('Labels in engagement: ' + this.stats4Graphs.label);
    this.labels = this.stats4Graphs.axisLabels as any;
  });

I hope this explanation clears things up for you!

Answer №2

When you're calling console.log outside of the subscription, make sure to consider how the getEngagement() method from the service returns an Observable. To handle this effectively, you can either assign your values within the subscription or define the stats4Graphs property as an Observable<Stats4Graphs> and utilize an async pipe in your template, like so:

stats4Graph: Observable<Stats4Graph>;

ngOnInit() {
  this.stats4Graph = this.profileService.getEngagement('UC__8h96Jwsaptaqh227Q9gg');
}
<div *ngIf="stats4Graph | async; let graph">
  <!-- You can now access `graph` as the value of the Observable -->
</div>

By following this approach, you won't need to manually subscribe to the getEngagement method of the service, as the async pipe takes care of unsubscribing when your component is destroyed.

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

Optimize data storage with javascript on Otree

I've been attempting to store the timestamp from a click in an Otree database, but I've tried using various codes without success. Here's the first code snippet: function myFunction() { var n = Date.now(); document.getElementById(" ...

What is the process of importing types in TypeScript?

Here is the export I am working with: import * as jwt from 'jsonwebtoken'; ... export type MyJsonWebToken = typeof jwt; Next, when attempting to use it in my code: export class AuthService { constructor( @Inject(constants.JWT) private ...

Utilizing Azure Active Directory for Authentication in Angular 13 and .NET Core Web API

I've set up a .NET CORE 6 Api as the backend and an Angular 13 frontend. I'm currently facing authentication issues with Angular using msal to call the protected .NET Core API, specifically the weatherforcast template. While I can successfully au ...

Establish a cookie using the PHP session's username

I have successfully implemented a general cookie for a one-time use scenario. However, I now need to create a cookie based on the username so that a message is displayed only once per user. My approach involves setting up a PHP session for the username ass ...

Automatically Populate list upon webpage initialization - React, Redux, Firebase

A webpage I am working on consists of two main components: Categories and Items By utilizing the function initCategories() called within the componentDidMount() lifecycle method of Categories, I successfully display all categories on the screen. The initC ...

AngularJS Cascading Dropdowns for Enhanced User Experience

There is a merchant with multiple branches. When I select a merchant, I want another dropdown list to display the data from merchant.branches. The following code does not seem to be fixing the issue: <label>Merchant:</label> <select ng-if= ...

Avoiding the Creation of Duplicate IDs in MongoDB

Within my backend using Node and MongoDB, I have a model that makes a reference to a collection of payers. Here is an example of how it is implemented: clients: [{ id: { type: mongoose.Schema.Types.ObjectId, ref: 'clients' } }], Currently, this ...

I had hoped to remove just one item, but now the entire database is being erased

I present it in this way <tr v-for="(foodItem, index) in filteredFoodItems"> <td>{{ foodItem.name }}</td> <td>{{ foodItem.price | currency('£') }}</td> <td>{{ foodItem.category }}< ...

Tips for closing process.stdin.on and then reopening it later

I've been facing a challenge with an exercise. In this exercise, the client will input a specific integer x, followed by x other y values separated by spaces. The output should be the sum of each y value, also separated by spaces. For example: Input: ...

I have encountered an issue in Angular 2 where a dynamic button, whose string value comes from the database, is not triggering the button's click function. Can someone assist me in resolving this issue?

The dataString extracted from the database appears as follows: "<button id =\"play\" class=\"btn btn-simple\" (click)=\"testVideo('math', 'ytv')\"><span class=\"fa fa-play\"></span ...

Component coding in Angular 2 allows for seamless integration and customization of Material

I am looking to initiate the start.toggle() function (associated with Angular 2 material md-sidenav-layout component) when the test() method is triggered. How can I execute md-sidenav-layout's start.toggle() in the app.component.ts file? app.componen ...

Issues with loading cascading drop down list data from database using MVC, JSON, and C#

Hello everyone, I'm fairly new to MVC/Javascript and have been experimenting with different tutorials in order to create a cascading drop down list for selecting State and City on an MVC view. In my latest attempt, I followed this example. While the ...

Clicking yields no results

let link = '<a href="javascript:void(0);" (click)="redirectToPage(store)" class="btn grey">' + displayText + '</a>'; Upon clicking the button on the page, nothing seems to be happening. Can you help me figure out what I&apo ...

When trying to read the text of an element, only the text of the first element is displayed

I have implemented a feature in ASP.Net MVC where I am fetching a list from a controller and displaying it in tile format on the view. However, when I click on a specific tile, I expect to see an alert message with the application name related to that par ...

Are you looking to generate a dynamic element (like a div) within a React application and then embed another React app within it?

I am in the process of developing a chat application using react-redux. This chat application is designed to handle multiple interactions concurrently, allowing users to switch between them seamlessly. class Chat extends React.Component { render() { ...

I need my styled component to make sure my inner div spans the entire width of its parent div

I'm having an issue with my NavDiv styled component not taking up the full height of my Wrapper styled component. I've tried setting the height using different units like percentage, em, rem, but it doesn't seem to work. It only works when u ...

Django base .js file causing JQuery compatibility issues

In my Django base template, I am utilizing app.js within a theme. I now need to implement a modal popup using AJAX, which requires calling a jQuery function. The error below occurs when trying to call the page where the modal popup button is located, which ...

Easily validate the contenteditable attribute of <td> element

I am currently working on a table that displays data from a MYSQL database. Whenever a user makes changes to an element in the table, I want the database to be updated using AJAX. Below is my JavaScript code for sending data in an editable row. function s ...

What steps should I take to enable users of my library to customize component templates as needed?

I created a customized component to enhance the appearance of bootstrap form controls, intended for use in various projects. I am considering transforming this into a library (a separate npm package with its own @NgModule), but some projects may wish to mo ...

Creating a File and Resource Manager for Your Express Application: Step-by-Step Guide

I'm interested in creating a website section where users can upload files, such as game mods, for others to download. I envision this section being able to handle a large volume of files and users. How can I achieve this scalability and what architect ...