How to globally import some module in Angular with Standalone Components?

203 Views Asked by At

I've some modules that I want to globally use everywhere in my app, so I don't want to have to declare them in every components.

Currently, I've to do the following:

@Component({
  selector: 'app-blank',
  templateUrl: './blank.component.html',
  imports: [RouterOutlet, MaterialModule, CommonModule],
  standalone: true,
  styleUrls: [],
})

I would like to avoid having to declare the MaterialModule and CommonModule.

I tried to remove them from the import list and in my app.config.ts:

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideAnimationsAsync(),
    importProvidersFrom(
      CommonModule, //<-- this
      MaterialModule,//<-- and this
      TablerIconsModule.pick(TablerIcons),
      FeatherModule.pick(allIcons)
    ),
  ],
};

This app.config.ts is referenced in my main.ts:

import { appConfig } from './app/app.config';

bootstrapApplication(AppComponent, appConfig).catch((err) =>
  console.error(err)
);

But when it runs, I get this in the compiler(which I don't if I have those 2 modules in my import):

X [ERROR] NG8001: 'mat-sidenav-container' is not a known element:                                                                                       
1. If 'mat-sidenav-container' is an Angular component, then verify that it is included in the '@Component.imports' of this component.
2. If 'mat-sidenav-container' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@Component.schemas' of this component to suppress this message. [plugin angular-compiler]

    src/app/layouts/blank/blank.component.html:4:0:
      4 │ <mat-sidenav-container
        ╵ ~~~~~~~~~~~~~~~~~~~~~~

  Error occurs in the template of component BlankComponent.

    src/app/layouts/blank/blank.component.ts:8:15:
      8 │   templateUrl: './blank.component.html',
        ╵                ~~~~~~~~~~~~~~~~~~~~~~~~


X [ERROR] NG8002: Can't bind to 'ngClass' since it isn't a known property of 'mat-sidenav-container'.
1. If 'mat-sidenav-container' is an Angular component and it has 'ngClass' input, then verify that it is included in the '@Component.imports' of this component.
2. If 'mat-sidenav-container' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@Component.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@Component.schemas' of this component. [plugin angular-compiler]

    src/app/layouts/blank/blank.component.html:5:2:
      5 │   [ngClass]="{
        ╵   ~~~~~~~~~~~~

  Error occurs in the template of component BlankComponent.

    src/app/layouts/blank/blank.component.ts:8:15:
      8 │   templateUrl: './blank.component.html',

It's an app that I just migrated from angular 16 to angular 17, I'm not sure if there is something more to do? What am I missing?

Here is my angular.json, since I had to modify it to use vite and the new builder:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "flexy": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "scss"
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:application",
          "options": {
            "allowedCommonJsDependencies": [
              "@swimlane/ngx-charts",
              "ng-apexcharts",
              "ngx-scrollbar",
              "rfdc",
              "apexcharts",
              "bezier-easing",
              "c3"
            ],
            "outputPath": "dist/flexy",
            "browser": "src/main.ts",
            "index": "src/index.html",
            "polyfills": ["zone.js"],
            "tsConfig": "tsconfig.app.json",
            "inlineStyleLanguage": "scss",
            "assets": ["src/favicon.ico", "src/assets"],
            "styles": [
              "src/styles.scss",
              "src/assets/scss/style.scss"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "12mb",
                  "maximumError": "12mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "12mb",
                  "maximumError": "12mb"
                }
              ],
              "outputHashing": "all"
            },
            "development": {
              "optimization": false,
              "extractLicenses": false,
              "sourceMap": true,
              "namedChunks": true
            }
          },
          "defaultConfiguration": "production"
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "configurations": {
            "production": {
              "buildTarget": "flexy:build:production"
            },
            "development": {
              "buildTarget": "flexy:build:development"
            }
          },
          "defaultConfiguration": "development"
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "buildTarget": "flexy:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "polyfills": ["zone.js", "zone.js/testing"],
            "tsConfig": "tsconfig.spec.json",
            "inlineStyleLanguage": "scss",
            "assets": ["src/favicon.ico", "src/assets"],
            "styles": ["src/styles.scss"],
            "scripts": []
          }
        }
      }
    }
  },
  "cli": {
    "analytics": false
  }
}

Seeing the first answers, I might have not been clear enough. The question is not about how to import specific component in my standalone components(like the RouterOutlet), but how to import "globally" for all my standalone components, a few modules containing all the components I want to import everywhere.

1

There are 1 best solutions below

5
NgDaddy On

If you have @angular/material migrated as well you can import standalone components from it:

import { NgIf } from '@angular/common';
import { Component } from '@angular/core';
import {
  MatSidenav,
  MatSidenavContainer,
  MatSidenavContent,
} from '@angular/material/sidenav';

@Component({
  selector: 'app-test',
  standalone: true,
  template: `
    <mat-sidenav-container *ngIf="showSidenav" class="example-container">
      <mat-sidenav mode="side" opened>Sidenav content</mat-sidenav>
      <mat-sidenav-content>Main content</mat-sidenav-content>
    </mat-sidenav-container>`,
  imports: [NgIf, MatSidenav, MatSidenavContainer, MatSidenavContent],
})
export class TestComponent {
  showSidenav = true;
}

The same for CommonModule members: *ngIf is a directive from it and this directive is standalone one which means you can import it on its own.

stackblitz@demo