6

I'm trying to select all textarea in one web page.

Is there a way to get all these elements in one single query and loop over them to add to each one a listener using the Renderer2 renderer.listen in order to implement a vertical auto expand of the textarea whenever I add text.

if I use @viewchild, I have to add manually a different template reference variable for each of them.

is it possible to have something similar to getElementsByTagName in angular and avoid direct access to DOM ?

HDJEMAI
  • 9,436
  • 46
  • 67
  • 93

1 Answers1

2

Directives are a perfect case for your scenario.

This isn't the final implementation but should give you a good idea how to use it.

import { Directive } from '@angular/core';

@Directive({
  selector: 'textarea[resize]'
})
export class HighlightDirective {

  @HostBinding('style.height.px') 
  height: number;

  @HostListener('change') 
  @HostListener('cut')
  @HostListener('paste')
  @HostListener('drop')
  @HostListener('keydown') 
  onClicked(event: Event) {
    this.resize();
  }

  constructor(private elementRef: ElementRef) {}

  resize() {
    const textArea = this.elementRef.nativeElement as HTMLTextAreaElement;
    this.height = textArea.scrollHeight;
  }
}

In your template decorate your textarea:

<textarea resize></textarea>
HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
cgatian
  • 22,047
  • 9
  • 56
  • 76
  • I think you are using a direct access to Dom ? but will look at it. – HDJEMAI Jan 12 '18 at 20:49
  • (revised answer for HostBinding) `ElementRef` gives you access to the native element in the DOM, in which case you need it because Angular currently [cannot read DOM properties](https://github.com/angular/angular/issues/18068). – cgatian Jan 12 '18 at 21:03
  • initially the scrollbar is visible, so I've added `overflow-y:hidden` but now I've to count the initial number of lines inside the `textarea` to set the initial value of number of rows... otherwise there is a number of lines that are hidden. – HDJEMAI Jan 12 '18 at 22:25
  • This directive looks good, just a small issue when doing enter the first time the upper line in the `textarea`, goes a little bit upper and whenever I remove a line or delete a letter the upper line shows completely inside, don't know why, may be we have to capture mouse down or its other thing ... but I've added `overflow-y: hidden` too, otherwise I keep see the scroll – HDJEMAI Jan 13 '18 at 00:58
  • It looks like by adding `@HostListener('keyup') onkeyup(event: Event) { this.resize(); }` its a little bit better. – HDJEMAI Jan 13 '18 at 01:16
  • @HDJEMAI cool! Yeah the implementation I provided basically matched what was requested. – cgatian Jan 13 '18 at 01:19