You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
scrutiny/webapp/frontend/src/@treo/directives/autogrow/autogrow.directive.ts

107 lines
2.9 KiB

import { Directive, ElementRef, HostBinding, HostListener, Input, OnDestroy, OnInit, Renderer2 } from '@angular/core';
import { Subject } from 'rxjs';
@Directive({
selector: 'textarea[treoAutogrow]',
exportAs: 'treoAutogrow'
})
export class TreoAutogrowDirective implements OnInit, OnDestroy
{
@HostBinding('rows')
rows: number;
// Private
private _padding: number;
private _unsubscribeAll: Subject<void>;
/**
* Constructor
*
* @param {ElementRef} _elementRef
* @param {Renderer2} _renderer2
*/
constructor(
private _elementRef: ElementRef,
private _renderer2: Renderer2
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
// Set the defaults
this.padding = 8;
this.rows = 1;
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Setter and getter for padding
*
* @param value
*/
@Input('treoAutogrowVerticalPadding')
set padding(value)
{
// Store the value
this._padding = value;
}
get padding(): number
{
return this._padding;
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Set base styles
this._renderer2.setStyle(this._elementRef.nativeElement, 'resize', 'none');
this._renderer2.setStyle(this._elementRef.nativeElement, 'overflow', 'hidden');
// Set the height for the first time
setTimeout(() => {
this._resize();
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Resize on 'input' and 'ngModelChange' events
*
* @private
*/
@HostListener('input')
@HostListener('ngModelChange')
private _resize(): void
{
// Set the height to 'auto' so we can correctly read the scrollHeight
this._renderer2.setStyle(this._elementRef.nativeElement, 'height', 'auto');
// Get the scrollHeight and subtract the vertical padding
const height = this._elementRef.nativeElement.scrollHeight - this.padding + 'px';
this._renderer2.setStyle(this._elementRef.nativeElement, 'height', height);
}
}