Git Product home page Git Product logo

Comments (5)

arturovt avatar arturovt commented on June 11, 2024 2

Hey, thanks for the repro.

Note we already had similar issues before.

TLDR:

// minute-counter.component.ts
providers: [ValueAccessorBase.getProviderConfig(forwardRef(() => MinuteCounterComponent))]

// value-accessor-base.class.ts
static getProviderConfig(useExisting: any): Provider {
  return {
    provide: NG_VALUE_ACCESSOR,
    useExisting: useExisting,
    multi: true
  };
}

Your current implementation contains the following code:

providers: [ValueAccessorBase.getProviderConfig(MinuteCounterComponent)]

But you're using forwardRef inside the getProviderConfig which isn't correct because the class reference should be captured before. The TS compiler generates a bit different code when the @UntilDestroy decorator is used on the class.

When there is no @UntilDestroy() decorator:

class MinuteCounterComponent extends ValueAccessorBase { ... }

MinuteCounterComponent.ɵcmp = ɵɵdefineComponent({
  type: MinuteCounterComponent,
  features: [
    ɵɵProvidersFeature([
      ValueAccessorBase.getProviderConfig(MinuteCounterComponent),
    ]),
    ɵɵInheritDefinitionFeature,
  ],
});

In the example above the MinuteCounterComponent is already "available" to be referenced and used below when the getProviderConfig is called, so forwardRef wouldn't even be required.

When the decorator is used:

var _class;
var MinuteCounterComponent_1;

let MinuteCounterComponent = (MinuteCounterComponent_1 =
  ((_class = class MinuteCounterComponent extends ValueAccessorBase {}),
  (_class.ɵcmp = ɵɵdefineComponent({
    type: _class,
    features: [
      ɵɵProvidersFeature([
        ValueAccessorBase.getProviderConfig(MinuteCounterComponent_1),
      ]),
      ɵɵInheritDefinitionFeature,
    ],
  })),
  _class));

MinuteCounterComponent = MinuteCounterComponent_1 = __decorate(
  [(0, UntilDestroy)()],
  MinuteCounterComponent
);

The MinuteCounterComponent_1, which is passed to getProviderConfig, equals undefined at the moment the function is being called. Because it's set later after the expression is evaluated completely. At the end the providers array has useExisting: forwardRef(() => undefined).

from until-destroy.

arturovt avatar arturovt commented on June 11, 2024 1

Because you're targetting es2022.

from until-destroy.

dancornilov avatar dancornilov commented on June 11, 2024

Thanks for quick and descriptive answer, your insights have shed light on the situation.

I wonder if there is a possibility to enhance the error message by incorporating additional validation or implementing supplementary logic. This improvement would greatly benefit developers encountering similar scenarios.

Interestingly, I have a project with a similar implementation of ControlValueAccessor & @UntilDestroy on Angular 14, which functions without encountering any errors.
It is worth noting that this error only started to manifest in Angular 15+.

from until-destroy.

arturovt avatar arturovt commented on June 11, 2024

I wonder if there is a possibility to enhance the error message by incorporating additional validation or implementing supplementary logic.

We can't because the error belongs to vague use-cases. This may happen in any implementation (e.g. ReactJS) using TypeScript and decorators.

from until-destroy.

dancornilov avatar dancornilov commented on June 11, 2024

Thanks again for your work 🙏.
(I have no other comments)

from until-destroy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.