javascriptangulartypescript

How to use standalone component in a non-standalone component?


I have a standalone component which I want to use in a non-standalone component without making this component standalone as well. Is this possible? I tried various way but always get errors.

I have this component

import { ChangeDetectionStrategy, Component } from '@angular/core';

@Component({
  selector: 'app-three-d-viewer',
  standalone: true,
  templateUrl: './three-d-viewer.component.html',
  styleUrls: ['./three-d-viewer.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ThreeDViewerComponent {

}

I want to use is it my app.component which is a non-standalone component.

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
}

I want to use it here

<div class="layout">
  <app-three-d-viewer></app-three-d-viewer>
</div>

and this is my app.module

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

I get this error


Error: src/app/app.component.html:2:3 - error NG8001: 'app-three-d-viewer' is not a known element:
1. If 'app-three-d-viewer' is an Angular component, then verify that it is part of this module.
2. If 'app-three-d-viewer' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.

2   <app-three-d-viewer></app-three-d-viewer>
    ~~~~~~~~~~~~~~~~~~~~

  src/app/app.component.ts:6:16
    6   templateUrl: './app.component.html',
                     ~~~~~~~~~~~~~~~~~~~~~~
    Error occurs in the template of component AppComponent.

What I tried is:

  1. import the standalone component in ThreeDViewerComponent the non-standalone component AppComponent with imports: [ThreeDViewerComponent] but get the error Error: src/app/app.component.ts:8:12 - error NG2010: 'imports' is only valid on a component that is standalone.

  2. Using a shared.module

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ThreeDViewerComponent } from './path/to/three-d-viewer.component';

@NgModule({
  declarations: [ThreeDViewerComponent],
  imports: [CommonModule],
  exports: [ThreeDViewerComponent]
})
export class SharedModule {}

and import it in AppModule but I get this error:

Error: src/app/app.module.ts:14:5 - error NG6002: This import contains errors, which may affect components that depend on this NgModule.

14     SharedModule
       ~~~~~~~~~~~~


Error: src/app/shared.module.ts:6:18 - error NG6008: Component ThreeDViewerComponent is standalone, and cannot be declared in an NgModule. Did you mean to import it instead?

6   declarations: [ThreeDViewerComponent],
                   ~~~~~~~~~~~~~~~~~~~~~


Error: src/app/shared.module.ts:8:13 - error NG6004: Can't be exported from this NgModule, as it must be imported first

8   exports: [ThreeDViewerComponent]
              ~~~~~~~~~~~~~~~~~~~~~




× Failed to compile.

What can I do?


Solution

  • The standalone component cannot be declared (Declarations Array) when it's standalone, so it needs to be imported (Imports Array) on a module, either the top level one, which can be used by all the component on the declarations array.

    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { AppComponent } from './app.component';
    import { HttpClientModule } from '@angular/common/http';
    import { ThreeDViewerComponent } from './path/to/three-d-viewer.component';
    
    @NgModule({
      declarations: [
        AppComponent,
      ],
      imports: [
        BrowserModule,
        HttpClientModule,
        ThreeDViewerComponent, // <- changed here!
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    

    Or you can import it to the shared module, only thing is that, you must export it also, for it to be visible in all the component that import the SharedModule.

    import { NgModule } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { ThreeDViewerComponent } from './path/to/three-d-viewer.component';
    
    @NgModule({
      declarations: [],
      imports: [CommonModule, ThreeDViewerComponent], // <- changed here!
      exports: [ThreeDViewerComponent]
    })
    export class SharedModule {}
    

    You got the error for imports array because, on the component that is standalone only does imports array exists, in a non standalone component, there is no imports array in the component decorator object.