andrei_f
andrei_f

Reputation: 198

Intercept&change input of 3rd party Angular component &

Is there a way to extend a component which is exported by a 3rd party library in such a way that I can intercept and change the value of a specific Input?An important mention is that the component already implements the `ngOnChanges` hook so, if I create a directive which targets the component, the directive's `ngOnChanges` hook is executed AFTER the component one.

If there is no other way to extend it and keep the original component selector, I'm OK to extend the parent component Class with a new selector, like:

@Component({
  selector: 'extended-component',
  template: '',
})
export class YourExtendedComponent extends ThirdPartyComponent implements OnChanges {
  @Input() adjustedInputValue: string;

  ngOnChanges(changes: SimpleChanges): void {
    // Check if the inputValue has changed
    if (changes.inputValue) {
      // Your logic to adjust the input value goes here
      this.adjustedInputValue = this.adjustInput(changes.inputValue.currentValue);
    }
  }

  private adjustInput(value: string): string {
    // Your custom logic to adjust the input value
    return value.toUpperCase(); // Example: Convert to uppercase
  }
}

The problem is that my ThirdPartyComponent has some component Providers:

@Component({
    selector: 'some-component',
    standalone: true,
    template: '',
    providers: [
        SomeInjectable,
        AnotherInjectable
    ],
    encapsulation: ViewEncapsulation.None
})

Would I end up with duplicate instances for SomeInjectable?

As I said, ideally I would try to achieve this without changing the initial compoennt selector.

Upvotes: 0

Views: 50

Answers (1)

Pawel Twardziak
Pawel Twardziak

Reputation: 804

No, when you extend a component A with another component B, the decorator Component of component B won't be taken into account (its imports as well). So, no worries.

Here you have an example stackblitz that shows this case. You will see this error in the console:

ERROR

Error: R3InjectorError(Environment Injector)[SomeInjectable -> SomeInjectable]:
NullInjectorError: No provider for SomeInjectable!

The code:

import {
  Component,
  inject,
  Injectable,
  ViewEncapsulation,
} from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';

@Injectable()
class SomeInjectable {
  constructor() {
    console.log('SomeInjectable->constructor');
  }
}

@Component({
  selector: 'some-component',
  standalone: true,
  template: `some-component {{name}}`,
  providers: [SomeInjectable],
  encapsulation: ViewEncapsulation.None,
})
export class SomeComponent {
  name = 'Angular';
}

@Component({
  selector: 'new-component',
  standalone: true,
  template: `new-component {{name}}`,
  providers: [
    /* SomeInjectable */
  ],
})
export class NewComponent extends SomeComponent {
  someInjectable = inject(SomeInjectable);

  override name = 'Angular 2';
}

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <h1>Hello from {{ name }}!</h1>
    <new-component></new-component>
  `,
  imports: [NewComponent],
})
export class App {
  name = 'Angular';
}

bootstrapApplication(App);

Upvotes: 0

Related Questions