import { Directive, ElementRef, OnInit, AfterContentInit, HostListener } from '@angular/core'; /** * Den första textarean (förslagsvis den enda) i komponenten som fbElastic appliceras på blir elastisk. Textareas som fbElastic appliceras på blir elastiska. * * Syntax: * * * */ @Directive({ selector: '[fbElastic]' }) export class FbElasticDirective implements OnInit, AfterContentInit { private element: HTMLElement; private textarea: HTMLTextAreaElement; constructor(elemntRef: ElementRef) { this.element = elemntRef.nativeElement; } ngOnInit(): void { // Use first textarea child if component is not a textarea this.textarea = this.element.tagName === 'TEXTAREA' ? this.element as HTMLTextAreaElement : this.element.getElementsByTagName('textarea')[0]; } ngAfterContentInit(): void { // Initial adjust on initial render setTimeout(() => { this.adjust.bind(this); this.adjust(0); }, 0); // "Que" adjust to be ran after template is rendered. Event loop lecture: https://www.youtube.com/watch?v=8aGhZQkoFbQ } @HostListener('input') onInput(): void { // This is run whenever the user changes the input. this.adjust(0); } @HostListener('blur') onblur(): void { setTimeout(() => { this.adjust.bind(this); this.adjust(0); }, 0); // "Que" adjust to be ran after the model has updated (for anteckning). } adjust(antal: number): void { // Width < 10 happens when the element is not rendered, wait 100ms and then try again, stop trying after 5 tries, just to stop it from looping forever if (this.textarea) { if (this.textarea.clientWidth < 10 && antal < 5) { setTimeout(() => { this.adjust(antal++); }, 100); } else { this.textarea.style.height = 'auto'; // This decreases height // The Element.scrollHeight read-only property is a measurement of the height of an element's content, including content not visible on the screen due to overflow. this.textarea.style.height = this.textarea.scrollHeight + 'px'; // This increases height } } } }