angular-tabler-icons icon indicating copy to clipboard operation
angular-tabler-icons copied to clipboard

Tabler Icons V2.40.0 does not work with Angular v17.0.0 using Standalone Components and SSR

Open DevJaGz opened this issue 2 years ago • 4 comments

This is how I import the icons:

  • First I pick the icons I need.

tabler-icons.constant.ts

import { IconBrandLinkedin, IconBrandGithub, IconBrandX } from 'angular-tabler-icons/icons';
import { OptionIcons } from 'angular-tabler-icons/lib/options.interfaces';

export const TABLER_ICONS: OptionIcons = {
  IconBrandLinkedin,
  IconBrandGithub,
  IconBrandX
}
  • Then I import them in the Icons module.

icons.module.ts

import { NgModule } from '@angular/core';
import { TablerIconsModule } from 'angular-tabler-icons';
import { TABLER_ICONS } from '../constants/tabler-icons.constant';

@NgModule({
  imports: [
    TablerIconsModule.pick(TABLER_ICONS)
  ],
  exports: [
    TablerIconsModule
  ]
})
export class IconsModule { }
  • By last, I import the Icons module into my standalone app configuration.

app.config.ts

import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';

import { IconsModule } from './modules/icons.module';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes), 
    provideClientHydration(),
    importProvidersFrom(IconsModule),
  ]
};

Based on the previous, once the app is started, the following error appeared:

NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`. Find more at https://angular.io/errors/NG0203

Versions to reproduce:

  • Ubuntu WSL
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.3 LTS
Release:        22.04
Codename:       jammy
  • bun 1.0.7
  • Angular 17.0.0 (standalone - SSR)

DevJaGz avatar Nov 09 '23 05:11 DevJaGz

You do not need to import IconsModule into app.config.ts. With standalone components, simply import the IconsModule into your component, like this:

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { IconsModule } from './icons.module';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet, IconsModule], // <----- import here
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'My App';
}

If you want to pick only specific icons in your standalone component, import the TablerIconsProvider like this:

import { Component } from '@angular/core';
import { TablerIconsModule, TablerIconsProvider } from 'angular-tabler-icons';
import { IconBrandGithub } from 'angular-tabler-icons/icons';


@Component({
  selector: 'app-standalone',
  templateUrl: './standalone.component.html',
  standalone: true,
  imports: [
    TablerIconsModule,
  ],
  providers: [
    TablerIconsProvider.pick({
      IconBrandGithub
    })
  ]
})
export class StandaloneComponent {
}

Then, you can use Angular Tabler Icons component the standard way, for example:

<i-tabler name="brand-github"></i-tabler>

Is it working for you?

pierreavn avatar Nov 12 '23 14:11 pierreavn

You do not need to import IconsModule into app.config.ts. With standalone components, simply import the IconsModule into your component, like this:

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { IconsModule } from './icons.module';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet, IconsModule], // <----- import here
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'My App';
}

If you want to pick only specific icons in your standalone component, import the TablerIconsProvider like this:

import { Component } from '@angular/core';
import { TablerIconsModule, TablerIconsProvider } from 'angular-tabler-icons';
import { IconBrandGithub } from 'angular-tabler-icons/icons';


@Component({
  selector: 'app-standalone',
  templateUrl: './standalone.component.html',
  standalone: true,
  imports: [
    TablerIconsModule,
  ],
  providers: [
    TablerIconsProvider.pick({
      IconBrandGithub
    })
  ]
})
export class StandaloneComponent {
}

Then, you can use Angular Tabler Icons component the standard way, for example:

<i-tabler name="brand-github"></i-tabler>

Is it working for you?

Hi @pierreavn sorry for the delay, I have been a bit bussy. I really appreciate your comment. Your approach did not work for me, now it shows me the next error:

ERROR RuntimeError2: NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`. Find more at https://angular.io/errors/NG0203
    at injectInjectorOnly (/projects/devjagz-portfolio/.angular/vite-root/devjagz-portfolio/node_modules/angular-tabler-icons/node_modules/@angular/core/fesm2022/core.mjs:908:5)
    at ɵɵinject2 (/projects/devjagz-portfolio/.angular/vite-root/devjagz-portfolio/node_modules/angular-tabler-icons/node_modules/@angular/core/fesm2022/core.mjs:998:53)
    at Object.TablerIconsModule_Factory (/projects/devjagz-portfolio/.angular/vite-root/devjagz-portfolio/node_modules/angular-tabler-icons/fesm2020/angular-tabler-icons.mjs:88:43)
    at Object.factory (/projects/devjagz-portfolio/.angular/vite-root/devjagz-portfolio/node_modules/@angular/core/fesm2022/core.mjs:6121:23)
    at eval (/projects/devjagz-portfolio/.angular/vite-root/devjagz-portfolio/node_modules/@angular/core/fesm2022/core.mjs:6028:10)
    at runInInjectorProfilerContext (/projects/devjagz-portfolio/.angular/vite-root/devjagz-portfolio/node_modules/@angular/core/fesm2022/core.mjs:873:5)
    at R3Injector.hydrate (/projects/devjagz-portfolio/.angular/vite-root/devjagz-portfolio/node_modules/@angular/core/fesm2022/core.mjs:6027:11)
    at R3Injector.get (/projects/devjagz-portfolio/.angular/vite-root/devjagz-portfolio/node_modules/@angular/core/fesm2022/core.mjs:5907:7)
    at injectInjectorOnly (/projects/devjagz-portfolio/.angular/vite-root/devjagz-portfolio/node_modules/@angular/core/fesm2022/core.mjs:912:12)
    at ɵɵinject (/projects/devjagz-portfolio/.angular/vite-root/devjagz-portfolio/node_modules/@angular/core/fesm2022/core.mjs:998:53) {
  code: -203
}

This is my current code:

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { TablerIconsModule, TablerIconsProvider  } from 'angular-tabler-icons';
import { IconBrandGithub } from 'angular-tabler-icons/icons';

@Component({
  selector: 'app-main-page',
  standalone: true,
  imports: [CommonModule, RouterOutlet, TablerIconsModule],
  providers: [
    TablerIconsProvider.pick({
      IconBrandGithub
    })
  ],
  templateUrl: './main-page.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MainPageComponent {

}

DevJaGz avatar Nov 27 '23 01:11 DevJaGz

I have the same issue. Were you able to solve your problem?

CedricLphn avatar Feb 26 '24 20:02 CedricLphn

Hi @DevJaGz ! You have to import also IconsModule into your MainPageComponent.

amineChenn avatar Mar 08 '24 23:03 amineChenn

Please use version 3.22.0: npm install [email protected]

pierreavn avatar Dec 07 '24 14:12 pierreavn