Dynamically increase the input width to the length of the line.
I am trying to create a field input
that dynamically expands at least in width with the length of the line entered by the user, possibly even multi-line. Is this possible with an element input
in Angular Material 2?
In a box textarea
from Angular Material 2, I was able to expand the text box in height rather than width with the following code:
<mat-form-field (keydown.enter)="onEnter()"
floatPlaceholder="never">
<textarea matInput
placeholder="Autosize textarea"
matTextareaAutosize
matAutosizeMinRows="1"
matAutosizeMaxRows="8">
</textarea>
</mat-form-field>
The case textarea
scrollbar
should be invisible or replaced with a smaller one. And the most important click Entershould not create a new line, but only trigger an action.
source to share
You can use ngStyle to bind the mat-form field width and height to the computed value and use the keyup event on the input to set this value. For example, here's an input whose width follows the number of characters over 8:
<mat-form-field style="min-width: 8ch;" [ngStyle]="{'width.ch': width}">
<input matInput (keyup)="width = $event.srcElement.value.length">
</mat-form-field>
Obviously, this is pretty rude. The tricky part is correctly calculating the width or height you need based on the content.
source to share
Now I have created a more suitable solution for this problem. After I found the perfect solution in jQuery and @Obsidian added the appropriate JS code . I tried to adapt it for Angular input
and came up with the following. I've also added some scripts that support cutting and pasting lines.
Here's a demo on StackBlitz and related code:
Template:
<style>
#invisibleTextID {
white-space: pre;
}
// prevents flickering:
::ng-deep .mat-form-field-flex {
width: 102% !important;
}
</style>
<mat-form-field
#formFieldInput
[ngStyle]="{'width.px': width}">
<input
#inputText
id="inputTextID"
matInput
[(ngModel)]="inString"
(paste)="resizeInput()"
(cut)="resizeInput()"
(input)="resizeInput()">
</mat-form-field>
<span #invisibleText id="invisibleTextID">{{ inString }}</span>
Resizing method:
@ViewChild('invisibleText') invTextER: ElementRef;
inString: string = '';
width: number = 64;
resizeInput() {
// without setTimeout the width gets updated to the previous length
setTimeout ( () =>{
const minWidth = 64;
if (this.invTextER.nativeElement.offsetWidth > minWidth) {
this.width = this.invTextER.nativeElement.offsetWidth + 2;
} else {
this.width = minWidth;
}
}, 0)
}
source to share