angulartypescriptionic-framework

Why is Angular asking for an standalone component, even though it is


Pretty much what the title says, I can't find what I'm doing wrong. Here's the code for circulo.component.ts:

import { Component, OnInit } from '@angular/core';
import { Circulo } from '../figura-geometrica';

@Component({
  selector: 'app-circulo',
  templateUrl: './circulo.component.html',
  styleUrls: ['./circulo.component.scss'],
  standalone: true,
})
export class CirculoComponent extends Circulo implements OnInit {

  override radio: number = 0;

  constructor(nombre:string, radio:number) {
    super(nombre, radio)
    this.radio = radio;
  }

   ngOnInit() {}

   override calcularPerimetro(): number {
    return this.radio * 2 * 3.1416
  }


}

This is what it's importing on the second line from circulo.component.ts, figura-geometrica.ts:

export abstract class FiguraGeometrica {
    nombre : string = "";

    constructor(nombre:string) {
        this.nombre = nombre;
    }

    abstract calcularPerimetro(): number
}

export class Circulo extends FiguraGeometrica {
    radio : number = 0;

    constructor(nombre:string, radio:number) {
        super(nombre)
        this.radio = radio;
    }
    override calcularPerimetro(): number {
        return this.radio * 2 * 3.1416
    }
}

export class TrianguloEscaleno extends FiguraGeometrica {

    ladoA : number = 0;
    ladoB : number = 0;
    ladoC : number = 0;

    constructor(nombre:string, ladoA:number, ladoB:number, ladoC:number) {
        super(nombre)
        this.ladoA = ladoA;
        this.ladoB = ladoB;
        this.ladoC = ladoC;
    }
    override calcularPerimetro(): number {
        return this.ladoA + this.ladoB + this.ladoC
    }
}

export class TrianguloEquilatero extends TrianguloEscaleno {    
    constructor(nombre:string, ladoA:number, ladoB:number, ladoC:number){
        super(nombre, ladoA, ladoB, ladoC)
    }
}

Now this is where I get the problem, home.page.ts:

import { Component } from '@angular/core';
import { IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/angular/standalone';
import { CirculoComponent } from "../modelo/circulo/circulo.component";

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
  imports: [IonHeader, IonToolbar, IonTitle, IonContent, CirculoComponent], <- there
  standalone: true,
})
export class HomePage {
  constructor() {}
}

imports: [IonHeader, IonToolbar, IonTitle, IonContent, CirculoComponent], <- that's what is giving me the problem, which is this:

Component imports must be standalone components, directives, pipes, or must be NgModules.(-992012)

I also think that figura-geometrica.ts is unnecessary, but that's how my teacher has done it, but with an easier example.


Solution

    1. You need to add the IonInput, IonItem, and IonList components to the imports array for CirculoComponent.
    import { IonInput, IonItem, IonList } from '@ionic/angular/standalone';
    
    @Component({
      ...,
      imports: [IonInput, IonItem, IonList],
    })
    export class CirculoComponent extends Circulo implements OnInit {
      ...
    }
    
    1. The arguments in the constructor of a component are dependency injectors. For your scenario, you need to add/register the Injection Token for nombre and radio into the providers either for the component or the root application/module. Next, use the @Inject() decorator to get the value from DI.
    import { Component, Inject, OnInit } from '@angular/core';
    import { IonInput, IonItem, IonList } from '@ionic/angular/standalone';
    
    @Component({
      selector: 'app-circulo',
      templateUrl: './circulo.component.html',
      styleUrls: ['./circulo.component.scss'],
      standalone: true,
      imports: [IonInput, IonItem, IonList],
      providers: [
        { provide: 'nombre', useValue: 'test' },
        { provide: 'radio', useValue: 1 },
      ],
    })
    export class CirculoComponent extends Circulo implements OnInit {
      constructor(
        @Inject('nombre') nombre: string,
        @Inject('radio') radio: number
      ) {
        super(nombre, radio);
        this.radio = radio;
      }
    }
    

    For adding the injection token to the root application:

    bootstrapApplication(App, {
      providers: [
        ...,
        { provide: 'nombre', useValue: 'test' },
        { provide: 'radio', useValue: 1 },
      ],
    });
    

    Demo @ StackBlitz