'Angular 12 - Character counter - Binding property input initialization of component in a directive

I am trying to build a "Character Counter" Angular directive for a custom component which I can't use ngModel to bind the value. (my-component shown below is really complex so, I ask to trust me and long term goal is to use the same directive thru different components). I have to intercept when the initialText input property is set, and of course when changedText is triggered

<my-component
      characterCount
      [initialText]="value"
      (changedText)="valueChange.emit($event)">
</my-component>

  @Input() initialText;
  @Output() changedText: EventEmitter<string> = new EventEmitter<string>();

I have already figured out how to intercept changedText


@Directive({
  selector: "[characterCount]",
})
...
  @HostListener("changedText", ["$event"])
  changeText(changedText){
    this.setCharacterCount(changedText);
  }

but I don't know how to intercept when the initialText property is set.

Thanks for your help guys.



Solution 1:[1]

Some time ago, in this SO someone ask about add a maxlength to a formControl

The same idea

@Component({
  selector: 'app-help',
  template: `<p class="count-help">{{_text}}</p>`,
  changeDetection: ChangeDetectionStrategy.OnPush,
  styleUrls: ['./count.component.css']
})
export class CountComponent {
  _text;

  @Input() set text(value) {
    if (value !== this._text) {
      this._text = value;
      this.cdr.detectChanges();
    }
  };
 constructor(private cdr: ChangeDetectorRef) { }

}

And the directive

@Directive({
  selector: '[characterCount]',
})
export class CountLengthDirective implements OnInit,OnDestroy {
  ref: ComponentRef<CountComponent>;
  subscription: any;
  constructor(
    @Self() private control: NgControl,
    private el: ElementRef,
    private vcr: ViewContainerRef,
    private resolver: ComponentFactoryResolver
  ) {}
  ngOnInit() {
      const factory = this.resolver.resolveComponentFactory(CountComponent);
      this.ref = this.vcr.createComponent(factory);
      this.subscription = this.control.valueChanges
        .pipe(startWith(this.control.value))
        .subscribe((res) => {
          this.ref.instance.text =this.control.value.length+' characters'
        });
  }
  ngOnDestroy() {
    this.subscription && this.subscription.unsubscribe();
  }

in this stackblitz

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Eliseo