Do someone have a great idea how to implement an ion-textarea which would be per default presented with 1 row but according what the user type could grow to max 3 rows?
Something like:
<ion-textarea #msgInput rows="1" maxLength="500" (keyup)="resize()"></ion-textarea>
But the question is, what to add in the resize method to achieve the goal?
@ViewChild('msgInput') msgInput: TextInput;
resize() {
// Something good, something bad? A bit of both!
}
3 Likes
Freak, took me way to much tiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiime just for that, but got it.
The tricks is: don’t use ion-textarea but textarea and don’t forget the ‘.px’ part to change the height dynamically.
Html:
<textarea #myInput id="myInput" rows="1" maxLength="500" (keyup)="resize()" [(ngModel)]="myStuff"></textarea>
Css:
#myInput {
width: calc(100% - 10px);
border: 0;
border-radius: 0;
background: transparent;
}
Ts:
@ViewChild('myInput') myInput: ElementRef;
resize() {
this.myInput.nativeElement.style.height = this.myInput.nativeElement.scrollHeight + 'px';
}
15 Likes
after following this solution , if i include placeholder , it comes as red colored , how to change it to default ?
Navil
May 4, 2017, 12:26am
4
And how to make it work with ion-textarea?
@Navil no idea, I only find a solution with textarea, but you are most welcomed to try and share you solution if you find it
@devanshsadhotra was probably a css issue, style.height chg the height not the color of the placeholder
Navil
May 4, 2017, 11:19am
6
Pretty sure, this is a bug from the ionic framework. I will try to find any workaround
got that fixed , by using text area instead of ion-textarea
1 Like
jhix
June 8, 2017, 10:50am
8
I found this solution:
<ion-item>
<ion-label floating>Model</ion-label>
<ion-textarea #myInput id="myInput" rows="1" maxLength="500" (keyup)="resize()" [(ngModel)]="model"></ion-textarea>
</ion-item>
@ViewChild('myInput') myInput: ElementRef;
resize() {
var element = this.myInput['_elementRef'].nativeElement.getElementsByClassName("text-input")[0];
var scrollHeight = element.scrollHeight;
element.style.height = scrollHeight + 'px';
this.myInput['_elementRef'].nativeElement.style.height = (scrollHeight + 16) + 'px';
}
11 Likes
Could you give a solution with more detail? Because I’ve got error “[ts] Cannot find name ‘ElementRef’” for variable ‘ElementRef’?
.
asger
June 12, 2017, 8:25am
10
I built on someone else’s code to make the following directive:
// An autoresize directive that works with ion-textarea
// Usage example: <ion-textarea autoresize></ion-textarea>
// Based on https://www.npmjs.com/package/angular2-autosize
import { Directive, HostListener, OnInit, ElementRef } from "@angular/core";
@Directive({
selector: "ion-textarea[autoresize]" // Attribute selector
})
export class TextareaAutoresize implements OnInit {
@HostListener("input", ["$event.target"])
onInput = (textArea: HTMLTextAreaElement): void => {
this.adjust();
}
constructor(public element: ElementRef) { }
ngOnInit(): void {
const waitThenAdjust = (trial: number): void => {
if (trial > 10) {
// Give up.
return;
}
const ta = this.element.nativeElement.querySelector("textarea");
if (ta !== undefined && ta !== null) {
this.adjust();
}
else {
setTimeout(() => {
waitThenAdjust(trial + 1);
}, 0);
}
};
// Wait for the textarea to properly exist in the DOM, then adjust it.
waitThenAdjust(1)
}
adjust = (): void => {
const ta = this.element.nativeElement.querySelector("textarea");
if (ta !== undefined && ta !== null) {
ta.style.overflow = "hidden";
ta.style.height = "auto";
ta.style.height = ta.scrollHeight + "px";
}
}
}
3 Likes
jhix
June 12, 2017, 4:36pm
11
Your error should be resolved by importing ElementRef through the following statement:
import { Component, ViewChild, ElementRef } from '@angular/core';
Great job! Works well! One small addition, it’s also good to add minimum height, in case you have a wider text area, then it won’t just to line height to only later expand:
min-height: 40px;
2 Likes
this works great! thank you.
does anyone know how the make is smaller again if i were to delete rows of text? when i type it expands but when i delete the text it stays expanded. i want it to return back to original size.
1 Like
you can try setting height to ‘auto’
calonzo
October 27, 2017, 7:42pm
15
Thank you for shared this solution
heeeerrrrrrrrrr thanks for this code it really solved my problem
chop kiss bro
To make resizing work for deleting text, I added a line to the resize method that first sets the textarea height to auto, and then does the resize based on scroll height. This clears the height and then recomputes as the user types. Seems to work for me even when the delete button is held down, and does not seem to introduce any visual glitches. (I haven’t tested across devices, only on my iPhone). My revised method looks like this:
resize() {
this.myInput.nativeElement.style.height = 'auto'
this.myInput.nativeElement.style.height = this.myInput.nativeElement.scrollHeight + 'px';
}
4 Likes
sampath
November 12, 2017, 2:31am
18
2 Likes
kfrager
November 16, 2017, 10:29pm
19
thank you!!
this worked. have to test it on devices first thought but int he browser testing so far so good.
I believe we should listen for only enter key event than every key stroke for more performance.
import { Directive, HostListener, ElementRef } from '@angular/core';
@Directive({
selector: 'ion-textarea[autosize]' // Attribute selector,
})
export class AutosizeDirective {
@HostListener('document:keydown.enter', ['$event']) onKeydownHandler(evt: KeyboardEvent) {
this.adjust()
}
constructor(public element:ElementRef) {
}
ngAfterViewInit(){
this.adjust()
}
adjust():void {
let textArea = this.element.nativeElement.getElementsByTagName('textarea')[0];
textArea.style.overflow = 'hidden';
textArea.style.height = 'auto';
textArea.style.height = (textArea.scrollHeight + 32) + "px";
}
}
2 Likes