Home > database >  Typescript - Object display correct datas but properties are undefined on access
Typescript - Object display correct datas but properties are undefined on access

Time:05-10

When I log the entire object all the datas are displayed but when I try to access the properties they are undefined. As if the object's properties where not mapped to their datas.

A component containing the data :

@Component({
  selector: 'app-card',
  templateUrl: './card.component.html',
  styleUrls: ['./card.component.scss'],
})
export class CardComponent implements OnInit, AfterContentInit, ISimulable {
  ...

  cardData?: ICardData;
  
  ...

  constructor(
    private simulationService: SimulationService,
    private dispatcher: DataDispatcherService
  ) {}
  
  ...

  getData(): void {
    var temp = this.dispatcher.getCardDataFromType(this.cardDataClass, {
      timestamp: '2021/10/10', model: this.radioValue as DataModels, distribution: 
      this.radioValue as DataDistributions
    });
    this.cardData = temp.rawData as ICardData;
    console.log(temp);
    console.log(temp.rawData);
  }

  ...

The console output : result of logs

The class displayed :

export class BoshGasDataCardDispatcher extends ADispatchedData {

  constructor(storageService: DataStorageService, input: ICardDispatchInput) {
    super(storageService, input);
  }

  /**
   * @param {DataStorageService} storageService The service fetching data.
   * @param {ICardDispatchInput} input The data used to fetch raw data.
   */
  protected async selectData(storageService: DataStorageService, input: ICardDispatchInput): Promise<void> {
    var tempData: ICalculation = await storageService.getCalculation(input.timestamp);
    var tempTranslation: ILanguageSettings = await storageService.getTranslationData("en-GB");

    var tempCard: ICardData = {title: tempTranslation.texts['Raceway_boshGasGroupBox_Text'], rows:[]};

    tempCard.rows.push({
      label: placeholder,
      value: placeholder,
      simValue: placeholder,
      unit: placeholder
    } as ICardRowData);

    tempCard.rows.push({
      label: placeholder,
      value: placeholder,
      simValue: placeholder,
      unit: placeholder
    } as ICardRowData);

    tempCard.rows.push({
      label: placeholder,
      value: placeholder,
      simValue: placeholder,
      unit: placeholder
    } as ICardRowData);
 
    tempCard.rows.push({
      label: placeholder,
      value: placeholder,
      simValue: placeholder,
      unit: placeholder
    } as ICardRowData);

    tempCard.rows.push({
      label: placeholder,
      value: placeholder,
      simValue: placeholder,
      unit: placeholder
    } as ICardRowData);
 
    tempCard.rows.push({
      label: placeholder,
      value: placeholder,
      simValue: placeholder,
      unit: placeholder
    } as ICardRowData);

    this.rawData = tempCard;
  }
}

The extended abstract class :

import { DataStorageService } from "../../core/services/data-storage.service";

export abstract class ADispatchedData{

  rawData: any;

  constructor(storageService: DataStorageService, input: any) {
    this.selectData(storageService, input);
  }

  /**
   * Fill rawData with the necessary data for the creating component.
   * @param {DataStorageService} storageService The service fetching data.
   * @param {any} input The data used to fetch raw data.
   */
  protected abstract selectData(storageService: DataStorageService, input: any): void;
}

ICardData file :

import { ICardRowData } from './card-row-data.interface';
export interface ICardData{
  readonly title: string;
  readonly rows: ICardRowData[];
  message?: string;
}

ICardRowData file :

export interface ICardRowData{

  readonly label: string;

  readonly value: number | string;

  simValue: number | string;

  readonly unit: string;
}

CodePudding user response:

The problem was in the implementations of the abstract class. I was adding the async keyword to the selectData method since it's not possible to add it on the abstract original one. However that isn't enough to cause my problem, what really f****d it up was to call that method in the constructor of the abstract class. To solve this I had to remove that call from the constructor and put it somewhere else.

Abstract class :

import { DataStorageService } from "../../core/services/data-storage.service";

export abstract class ADispatchedData{

  rawData: any;

  constructor(protected storageService: DataStorageService, input: any) {
   // Removed the call to selectData
   // Put the service as protected to avoid redundancy and ease the use of selectData
  }

  abstract selectData(input: any): Promise<void>; 
  // Added the Promise<void> for consistency
  // Removed the service from the parameters, now a protected property 
}

Example of an implementation :

...

export class OxycoalCardDispatcher extends ADispatchedData {

  constructor(storageService: DataStorageService, input: ICardDispatchInput) {
    super(storageService, input);
  }

  async selectData(input: ICardDispatchInput): Promise<void> {
    var tempData: ICalculation = await this.storageService.getCalculation(input.timestamp);
    var tempTranslation: ILanguageSettings = await this.storageService.getTranslationData("en-GB");

    var tempCard: ICardData = {title: tempTranslation.texts["Raceway_OxyCoalGroupBox_Text"], rows:[]};

    tempCard.rows.push({
      label: placeholder,
      value: placeholder,
      simValue: placeholder,
      unit: placeholder
    } as ICardRowData);

    this.rawData = tempCard;
  }
}

Where the call is now done :

async getCardDataFromType(dataClass: Type<ADispatchedData>, input: ICardDispatchInput): Promise<ADispatchedData> {
    var temp = new dataClass(this.storageService, input);
    await temp.selectData(input);
    return temp;
  }
  • Related