pierreavn / angular-tabler-icons

Tabler Icons components library for your Angular applications
https://www.npmjs.com/package/angular-tabler-icons
MIT License
21 stars 2 forks source link

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

Open DevJaGz opened 8 months ago

DevJaGz commented 8 months ago

This is how I import the icons:

export const TABLER_ICONS: OptionIcons = { IconBrandLinkedin, IconBrandGithub, IconBrandX }


- Then I import them in the Icons module.
> `icons.module.ts`
```typescript
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 { }

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: 

```bash
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:

pierreavn commented 7 months ago

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?

DevJaGz commented 7 months ago

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 {

}
CedricLphn commented 4 months ago

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

amineChenn commented 4 months ago

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