Home > Software engineering >  Angular / TS - Get Type<SomeClass> from string
Angular / TS - Get Type<SomeClass> from string

Time:05-05

I have a component which is used many times to display different data. To know which data to display the component gets a string as an @Input() (I'd rather directly get a Type<SomeClass> but that doesn't seem possible). I then use that string to know which class to instantiate to get the correct data. However I can't find any way to get a Type<SomeClass> from that string.

Html file displaying card components :

<app-card cardData="SomeClassName"></app-card>
<!-- Here I wish I could just give the class type -->
<app-card cardData="SomeOtherClassName"></app-card>
...

Service managing the creation of the required class :

@Injectable({
  providedIn: 'root'
})
export class SomeService {

  constructor(private someOtherService: SomeOtherService) {
  }

  getDataFromType(dataClass: Type<SomeAbstractClass>, input: any): SomeAbstractClass {
    return new dataClass(this.someOtherService, input);
  }

}

Card component's files :

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

  @Input() cardData: string | undefined = undefined;
  
  rowsData: SomeAbstractClass;

  constructor(private someService: SomeService) {
    rowsData = someService.getDataFromType(/* cardData as Type<SomeAbstractClass> */);
  }
<div *ngFor="let data of rowsData">
  <div>
    {{ data.label }}
  </div>
  <div>
    {{ data.value }}
  </div>
  <div>
    <em>{{ data.metric }}</em>
  </div>
</div>

CodePudding user response:

I finally found a way to directly pass Type<SomeAbstractClass> in the html. I'm using a pipe containing the values I want to be able to pass.

Const file :

export const cardDataClasses = {
  name : SomeAbstractClass, 
...
};

export const radioOptionsDist = [
  ...
];

export const radioOptionsRw = [
  ...
];

Pipe :

@Pipe({
  name: 'const'
})
export class ConstPipe implements PipeTransform {

  transform(value: string, args?: any) {
    return {
      cardDataClasses: cardDataClasses,
      radioOptionsDist: radioOptionsDist,
      radioOptionsRw: radioOptionsRw,
    };
  }

}

Use of the pipe :

<app-card
      [cardDataClass]="('' | const).cardDataClasses.desiredClass"
></app-card>

This way I'm directly using the desired type in my method :

ngOnInit(): void {
    this.rawData = this.dispatcher.getCardDataFromType(this.cardDataClass);
}
  • Related