1

I have a directive in Angular that should read it's host element's input selectionStart, selectionEnd values. I do this in my custom directive:

@Directive({ selector: '[inputBehavior]', }) export class InputBehaviorDirective { public constructor( private el: ElementRef ) {} @HostListener('keydown', ['$event']) onKeyDown(event: KeyboardEvent): void { let { selectionStart, selectionEnd } = this.el.nativeElement as HTMLInputElement; } } 

host element's template looks like this:

<div class="input-field"> <div class="container"> <input [formControl]="formElement" /> </div> </div> 

host's typescript file:

@UntilDestroy() @Component({ selector: 'input-field', templateUrl: './input-field.component.html', styleUrls: ['./input-field.component.scss'], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputFieldComponent), multi: true, }, ], }) export class InputFieldComponent implements ControlValueAccessor { public formElement = new FormControl(); public writeValue(obj: number | string | undefined): void { this.formElement.setValue(obj?.toString()); } public registerOnChange(fn: any): void { } public registerOnTouched(fn: any): void {} public setDisabledState?(isDisabled: boolean): void {} } 

i use directive like this:

<input-field InputBehavior formControlName="height" > </input-field> 

but selectionStart and selectionEnd stay undefined. I want to apply the directive to the ControlValueAccessor host element as whole and not to the native html input element within host element's tempalte. So NOT like this:

<div class="input-field"> <div class="container"> <input InputBehavior [formControl]="formElement" /> </div> </div> 

so my question is, how to read selectionStart and selectionEnd values of the host element by applying the directive to it?

1 Answer 1

2

You can "reach" the input using el.nativeElement.getElementsByTag('input')[0]

@HostListener('keydown', ['$event']) onKeyDown(event: KeyboardEvent): void { const inputElement=this.el.nativeElement.getElementsByTag('input')[0] let { selectionStart, selectionEnd } = inputElement as HTMLInputElement; console.log(selectionStart, selectionEnd) } 

Another option can be change your directive in the way

export class InputBehaviorDirective { public inputElement!:HTMLInputElement; //<--add a variable public public constructor( private el: ElementRef ) {} @HostListener('keydown', ['$event']) onKeyDown(event: KeyboardEvent): void { //use the variable inputElement let { selectionStart, selectionEnd } = this.inputElement as HTMLInputElement; console.log(selectionStart, selectionEnd) } } 

And your InputFieldComponent like

The template

<div class="input-field"> <div class="container"> <!--Add a template reference variable--> <input #myinput [formControl]="formElement" /> </div> </div> 

In your .ts, inject in constructor the directive and use ViewChild with a setter

 @ViewChild('myinput',{static:true}) set _myInput(value:any) { if (this.behaviorDirective) this.behaviorDirective.inputElement=value; } constructor(@Host() @Optional() private behaviorDirective:InputBehaviorDirective){ } 
Sign up to request clarification or add additional context in comments.

3 Comments

The inputElement can be defined as @Input() inputElement!: HTMLElement; in the directive and then assigned in the template as <input #myinput [formControl]="formElement" inputBehavior [inputElement]="myinput"> and you can skip the part with the @ViewChild setter and the DI injector - which in my case, didn't work: I was correctly setting the inputElement in the setter, but despite this it was undefined when the directive code was reached.
@Rekesoft, see that this directive is because you want to "reach" an inner input tag. To "reach" the own element (the element where is added the directive -as your example-) you can simply inject ElementRef in constructor:constructor(private el:ElementRef){..}. NOTE: To access to the HTMLelement, from this.el, you use this.el.nativeElement
Oh yes, I see, I hadn't read the OP's question too carefully.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.