angularangular-libraryangular19

Using input Signal in Angular Library


When using an Angular (19) Library project within another Angular 19 Application project (these are separate projects) using npm link, I get following runtime error when building the application for production:

ERROR Error: NG0203: inputFunction2() can only be used within an injection 
context such as a constructor, a factory function, a field initializer, or 
a function used with `runInInjectionContext`. Find more at 
https://angular.dev/errors/NG0203

(In order to receive this error, I set "optimization": false in angular.json.)

I am confused as I believe that I am within a injection context (see example of the component). However, when I run the project in the development environment using npm run start, then the application works like a charm.

The issue is an input signal in my component (full minimal working example later in question):

label = input<string>('');

If I remove that, it works well. I also tried to use @Input with a Signal but I get a similar error.

Is it not possible to use Signals in an Angular Library project?


I have an Angular (19) Library project:

ng new components --create-application=false
ng generate library my-components
ng generate component my-components/info-tooltip

The library is added to the application project using npm link respectively npm link my-components. (As mentioned, everything works very well in the development enviroment.)

A minimal version of InfoTooltipComponent that reproduces the issue:

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

@Component({
  selector: 'app-info-tooltip',
  imports: [],
  template: '<p>{{label()}}</p>',
  styles: [],
  encapsulation: ViewEncapsulation.ShadowDom,
})
export class InfoTooltipComponent {

  label = input<string>('');

}

Then in my application project, I am using the component as following:

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

import { InfoTooltipComponent } from 'my-components';

@Component({
  selector: 'app-test',
  imports: [InfoTooltipComponent],
  template: `
    <app-info-tooltip label="Hello, World!"></app-info-tooltip>
  `,
  styles: [],
})
export class TestComponent {
  
}

Solution

  • Matthieu Riegler pointed out in his comment that I probably have 2 different instances of the core package. Unfortunately I was not able to figure out how to have only one instance while using npm link. I hope someone else comes along with a solution.

    Meanwhile, since npm link is not working in production, I decided to write a build.sh using npm pack script that is called when building the application:

    #!/bin/bash
    
    libraryPath=/path/to/projects/components
    applicationPath=/path/to/projects/application
    
    cd "$libraryPath"
    ng build
    
    cd "$libraryPath/dist/my-components"
    file=$(npm pack)
    
    cd "$applicationPath"
    npm install "$libraryPath/dist/my-components/$file"
    npm run build
    
    rm "$libraryPath/dist/my-components/$file"
    

    (This script has obviously room for improvement. Error handling omited for simplicity in this example.)