question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

@Self() decorated dependency throws an error

See original GitHub issue

Type of Issue

[X] Bug Report
[ ] Feature Request

Description

With the new ng-packagr@3.0.0-rc.5 when building my package I noticed an error:

BUILD ERROR
: No provider for NgControl ("[ERROR ->]<custom-form-field></custom-form-field>")

The line it originated from came from the constructor of a custom form component using a ControlValueAccessor, it seems that @Self() decorator made the DI fail. If I remove the build passed again.

When using the @Self() decorator, the only place allowed to find the injector is the component itself.

The same issue doesn’t appear for other DI-decorators like @Host() and @Optional

How To Reproduce

Setup a minimal custom form field component using the @Self() decorator.

import { Component, Self } from '@angular/core';
import { ControlValueAccessor, NgControl } from '@angular/forms';

@Component({
  selector: 'custom-form-field',
  template: ''
})
export class CustomFormFieldComponent implements ControlValueAccessor {
  constructor(
    @Self() public controlDir: NgControl
  ) {
    controlDir.valueAccessor = this;
  }

  onChange: (val: any) => void;
  onTouched: () => void;

  writeValue(val: any) {

  }

  registerOnChange(fn: (val: any) => void) {
    this.onChange = (val) => fn(val);
  }

  registerOnTouched(fn: any) {
    this.onTouched = fn;
  }
}

When building this package where this file is included it will result into:

BUILD ERROR
: No provider for NgControl ("[ERROR ->]<custom-form-field></custom-form-field>")

Expected Behaviour

I assume it would be able to build this just fine, as the module where the component is used is using the ReactiveFormsModule which provides this NgControl. Not sure if ng-packagr has special rules in place for injecting dependencies with @Self().

Version Information

ng-packagr:            3.0.0-rc.5
@angular/compiler:     6.0.2
rollup:                0.58.2
tsickle:               0.27.5
typescript:            2.7.2

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
alan-agius4commented, May 22, 2018

This doesn’t seem to be a bug, ngControl can be optional and thus apart from ‘self’ one should add ‘optional’ as well, as ngControl doesn’t get inject like a normal service for instance like httpClient, it gets injected based on the usage of the component.

Check an example; https://github.com/angular/material2/blob/master/src/lib/input/input.ts

Also ng-packagr doesn’t have any logic for this, its alll done by the Angular Compiler.

1reaction
abbazabactocommented, May 22, 2018

Thanks for the amazing quick reply @alan-agius4

Adding @Optional() seems to make the compiler happy:

constructor(
    @Optional() @Self() public controlDir: NgControl,
Read more comments on GitHub >

github_iconTop Results From Across the Web

This constructor is not compatible with Angular ...
Error : This constructor is not compatible with Angular Dependency Injection because its dependency at index 0 of the parameter list is invalid....
Read more >
Dependency injection in action
The host HeroBioComponent doesn't have its own LoggerService provider. Angular throws an error if you haven't also decorated the property with @Optional() ....
Read more >
Dependencies with yield - FastAPI
If you use a try block in a dependency with yield , you'll receive any exception that was thrown when using the dependency....
Read more >
Angular & Dependency Injection: tricks with Decorators
The Self Decorator limits the search for the dependency to the current injector. Normally, Angular would search for the dependency's ...
Read more >
ASP.NET Core Dependency Injection Deep Dive
If you want to instantiate a singleton yourself, you can do this: services.AddSingleton<IDataService>(new DataService());. It allows for one ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found