autosize textarea in angular2
Asked Answered
E

11

24

I am working on angular2 applciation. i have a requirement to autosize textarea. I am trying to reuse the angular2-autosize from https://github.com/stevepapa/angular2-autosize

Followed the readme, But I am getting the below error

Uncaught Error: Module build failed: Error: ENOENT: no such file or directory, open 'C:\Users\Vipin\SampleApp\node_modules\angular2-autosize\angular2-autosize.js'.

Please suggest how to overcome this issue.

Eld answered 16/3, 2017 at 7:27 Comment(1)
If by chance you are using Angular Material, here is a great solution: https://mcmap.net/q/321675/-change-size-of-textareaGuardrail
M
25

Update (15.04.2018) Managed to package it, now its available as

npm install ngx-autosize

https://github.com/chrum/ngx-autosize

Old answer:

I had the same problem today and got it fixed! Please check my fork: https://github.com/chrum/angular2-autosize

Until PR is merged try:

npm install https://github.com/chrum/angular2-autosize.git --save

And then in your code, because it's slightly different, you just import module not directive...

so instead of:

import {Autosize} from 'angular2-autosize';

@NgModule({
  ...
  declarations: [
    Autosize
  ]
  ...
})

you should have:

import {AutosizeModule} from 'angular2-autosize';

@NgModule({
  ...
  imports: [
    AutosizeModule
  ]
  ...
})
Mullen answered 18/3, 2017 at 22:36 Comment(3)
Hi, do you want to support angular5 also ?Capillarity
will check its support asapMullen
ok, i checked it quickly and in all of my projects i had to lock typescript at 2.4.2 to make it work... i guess its time to properly package it and publish on npm so there are no issues like thatMullen
A
37

The requested behaviour is already implemented in angular material as documented here: Angular Material Input Autosize. This is especially useful if you are using angular material anyways.

Just use cdkTextareaAutosize as in the example:

<textarea cdkTextareaAutosize></textarea>
Ably answered 11/4, 2019 at 16:20 Comment(6)
This should be marked as an easier solution! ThanksGiusto
@SnowBases, not really. Not everyone wants all the input lag Material inputs introduce.Anoa
@Anoa i am not that experienced with angular material. may you provide some sources that support that statement. It might be a nice extension to the answer.Ably
Angular material directive github.com/angular/components/blob/master/src/cdk/text-field/…Hypallage
I think this should be the accepted solution.Vanderbilt
strange, added but nothing happensMonet
M
25

Update (15.04.2018) Managed to package it, now its available as

npm install ngx-autosize

https://github.com/chrum/ngx-autosize

Old answer:

I had the same problem today and got it fixed! Please check my fork: https://github.com/chrum/angular2-autosize

Until PR is merged try:

npm install https://github.com/chrum/angular2-autosize.git --save

And then in your code, because it's slightly different, you just import module not directive...

so instead of:

import {Autosize} from 'angular2-autosize';

@NgModule({
  ...
  declarations: [
    Autosize
  ]
  ...
})

you should have:

import {AutosizeModule} from 'angular2-autosize';

@NgModule({
  ...
  imports: [
    AutosizeModule
  ]
  ...
})
Mullen answered 18/3, 2017 at 22:36 Comment(3)
Hi, do you want to support angular5 also ?Capillarity
will check its support asapMullen
ok, i checked it quickly and in all of my projects i had to lock typescript at 2.4.2 to make it work... i guess its time to properly package it and publish on npm so there are no issues like thatMullen
L
17

you can do like this without using the package. its simple

in controller like below

autogrow(){
  let  textArea = document.getElementById("textarea")       
  textArea.style.overflow = 'hidden';
  textArea.style.height = '0px';
  textArea.style.height = textArea.scrollHeight + 'px';
}

and in html like below

<textarea id="textarea" (keyup)="autogrow()" ></textarea>
Landwehr answered 11/6, 2017 at 19:41 Comment(5)
Although this works, it breaks Angular's philosophy (ie do NOT directly manipulate the DOM). Rather than use document.getElementById, use @ViewChild to get a ref to the textarea (since it is after all a child of the component)Galangal
Good Idea, but the view gets ugly when doing lots of height = 0px then increase, specially in text area with more lines than the entire viewport.Bine
Resetting the height to 0px is not necessary, and can be done in more smart waysCollop
And what are those smart ways?Arrowwood
Yes, we still do not know what the smarter ways are ^^Orsini
H
10

Why you need plugins for this, it's as simple as :

<textarea (keyup)="autoGrowTextZone($event)"></textarea>

and

autoGrowTextZone(e) {
  e.target.style.height = "0px";
  e.target.style.height = (e.target.scrollHeight + 25)+"px";
}
Hiding answered 8/2, 2019 at 23:13 Comment(1)
How to do for the detailed page ?Brainwashing
D
7

Slightly modified answer for tanveer's answer would be to use @ViewChild

@ViewChild('textArea', { read: ElementRef }) textArea: ElementRef;

public autoGrow() {
 const textArea = this.textArea.nativeElement;
 textArea.style.overflow = 'hidden';
 textArea.style.height = '0px';
 textArea.style.height = textArea.scrollHeight + 'px';
}

And in the HTML it would be

<textarea (keyup)="autoGrow()" #textArea></textare>
Dished answered 29/11, 2018 at 13:39 Comment(2)
As MohammadKermani commented on Tanveer's answer, "Resetting the height to 0px is not necessary, and can be done in more smart ways"Anoa
If you have more then one textarea elements: @ViewChild('textArea1', { read: ElementRef }) textArea1: ElementRef; @ViewChild('textArea2', { read: ElementRef }) textArea2: ElementRef; public autoGrow(name) { const textArea = this[name].nativeElement; textArea.style.overflow = 'hidden'; textArea.style.height = '0px'; textArea.style.height = textArea.scrollHeight - 20 + 'px'; }Babul
S
6

The solution that worked for me on IE as well as in the other browser

// Usage example: <textarea autoresize></textarea>

import { ElementRef, HostListener, Directive} from '@angular/core';

@Directive({
    selector: 'textarea[autosize]'
})

export class Autosize {
 @HostListener('input',['$event.target'])
  onInput(textArea: HTMLTextAreaElement): void {
    this.adjust();
  }
  constructor(public element: ElementRef){
  }
  ngAfterContentChecked(): void{
    this.adjust();
  }
  adjust(): void{
    this.element.nativeElement.style.overflow = 'hidden';
    this.element.nativeElement.style.height = 'auto';
    this.element.nativeElement.style.height = this.element.nativeElement.scrollHeight + "px";
  }
}

Add the below code to the APp.Module.ts

@NgModule({
  declarations: [
    Autosize
  ]
})

Use the tag on the HTML

 <textarea autosize></textarea>
Skerry answered 13/6, 2019 at 2:16 Comment(0)
V
5

Simply

You can use as below:

<textarea [rows]="text.split('\n').length || 2">{{text}}</textarea>

or

create a function in ts :

  getHeight(content) {
    const v1 = Math.floor(content.length / 50);
    const v2 = content.split('\n').length;
    return Math.max(v1,v2)
  }

HTML:

<textarea [rows]="getHeight(text) || 2">{{text}}</textarea>
Vitalize answered 28/12, 2020 at 14:12 Comment(1)
Simply brilliant!Bosley
C
3

Create the directive from angular-cli and add following code

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
selector: '[appAutoGrow]'
})
export class AutoGrowDirective {

constructor(public element: ElementRef) {
}
@Input() maximumHeight: number; // based on pixel
@Input() minHeight: number; // based on pixel
@HostListener('input', ['$event.target'])
@HostListener('cut', ['$event.target'])
@HostListener('paste', ['$event.target'])
@HostListener('change', ['$event.target'])

ngOnInit(): void {
    this.adjustCustom();
}

adjustCustom(): void {
    const element = this.element.nativeElement;
    element.style.height = this.minHeight + 'px';
    element.style.height = (element.scrollHeight) + 'px';
    if (element.scrollHeight <= this.maximumHeight) {

        element.style.overflowY = 'hidden'
        delete element.style.maxHeight
    } else {

        element.style.overflowY = 'scroll'
        element.style.maxHeight = this.maximumHeight + 'px';
    }

}
}

and use the directive as follows

<textarea autofocus [maximumHeight]="200" [minHeight]="43" appAutoGrow></textarea>
Croix answered 10/4, 2019 at 8:26 Comment(0)
C
1

I know the topic is quite old but I just change tanveer's answer to enter maximum Height as well.

    import { Directive, ElementRef, OnInit, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[appAutoResize]',

})
export class AutoResizeDirective implements OnInit {
  constructor(public element: ElementRef) {
  }
  @Input() maximumHeight: number; // based on pixel
  @HostListener('input', ['$event.target'])
  ngOnInit(): void {
    this.adjust();
  }

  adjust(): void {
    const ta = this.element.nativeElement;
    const maxHeghit = this.maximumHeight;
    ta.style.overflow = 'hidden';
    ta.style.height = 'auto';
    if (ta.scrollHeight <= maxHeghit) { // while current height is less than maximumHeight
      ta.style.height = ta.scrollHeight + 'px';
    } else { // greater than maximumHeight
      ta.style.height = maxHeghit + 'px';
      ta.style.overflow = 'auto';
    }
  }

}

So, you will have control on the style behavior.
I hope it can help.

Caulfield answered 31/1, 2019 at 22:7 Comment(0)
S
0

Here is the implementation of autosize in a directive which you can reuse on any textarea in your project.

import { Directive, Input, HostBinding } from '@angular/core';

@Directive({
    selector: 'textarea[autosize]'
})

export class TextareaAutosizeDirective {

    private _ngModel: any;

    public get ngModel(): any {
        return this._ngModel;
    }

    @Input()
    public set ngModel(value: any) {
        if (this._ngModel !== value) {
            this._ngModel = value;
            this.resize();
        }
    }

    @HostBinding('rows')
    public rows: number;

    @Input()
    public minRows: number = 1;

    constructor() {}

    private resize() {
        this.rows = !this._ngModel ? this.minRows : this.ngModel.split('\n').length;
    }

}

You can use it in a following way:

<textarea autosize minRows="2" [(ngModel)]="property"></textarea>

By adding autosize textarea becomes automatically resized. You can also specify minimum number of rows which textarea has.

Spinneret answered 10/5, 2022 at 14:0 Comment(0)
P
0

I am a bit late but let me provide my answer as well. Just simply follow the following

  adjustTextareaHeight() {
    const textarea: HTMLTextAreaElement = document.querySelector('textarea');
    textarea.style.height = 'auto';
    textarea.style.height = `${textarea.scrollHeight}px`;
  }
<textarea (input)="adjustTextareaHeight()"></textarea>
Parmenides answered 18/8, 2023 at 17:0 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.