将输入宽度动态扩展到字符串的长度
Expand input width dynamically to the length of string
我正在尝试创建一个 input
字段,该字段至少在宽度上随用户输入的字符串长度动态扩展,甚至可能是多行。
Angular Material 2 中的 input
元素可能吗?
使用 Angular Material 2 中的 textarea
字段,我只能使用以下代码扩展高度的文本区域,而不是宽度:
<mat-form-field (keydown.enter)="onEnter()"
floatPlaceholder="never">
<textarea matInput
placeholder="Autosize textarea"
matTextareaAutosize
matAutosizeMinRows="1"
matAutosizeMaxRows="8">
</textarea>
</mat-form-field>
在 textarea
的情况下,scrollbar
应该是不可见的或被较小的替换。最重要的是,按 Enter 不应创建新行,而只会触发一个操作。
您可以使用 ngStyle 将 mat-form-field 的宽度绑定到计算值,并使用输入上的输入事件来设置该值。例如,这里有一个宽度跟随超过 64px 的文本宽度的输入:
<mat-form-field [ngStyle]="{'width.px': width}">
<input #elasticInput matInput (input)="resize()">
</mat-form-field>
<span #hiddenText style="visibility: hidden; white-space: pre;">{{elasticInput.value}}</span>
export class InputTextWidthExample {
@ViewChild('hiddenText') textEl: ElementRef;
minWidth: number = 64;
width: number = this.minWidth;
resize() {
setTimeout(() => this.width = Math.max(this.minWidth, this.textEl.nativeElement.offsetWidth));
}
}
显然,此示例使用隐藏的 span 元素来获取文本宽度,这有点 hacky。计算字符串宽度的方法肯定不止一种,包括 this.
我现在为这个问题创建了一个更合适的解决方案。在我在 jQuery 中找到完美的解决方案后,@Obsidian 添加了 corresponding JS code。我尝试将其改编为 Angular input
并提出以下内容。
我还添加了一些支持剪切和粘贴字符串的场景。
Here is a demo on StackBlitz及对应代码:
模板:
<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>
调整大小方法:
@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)
}
我需要 matInput
在 mat-table
内的动态宽度(动态大小),我尝试了几种基于 的方法。但是,根据呈现的 table 单元查看动态数量的 <span>
元素是不切实际的。因此,我想出了一个比较实用的解决方案:
每当数据更新时,我创建一个 <span>
元素,用更新的数据填充它,将它添加到 HTML body
(或 div
中我的情况),提取 <span>
的 offsetWidth
并立即将其从 HTML 文档中删除。在测试时,我没有观察到任何闪烁或渲染问题(尽管我认为这是可能的)。
模板
...
<!-- col1 Column -->
<ng-container matColumnDef="col1">
<th *matHeaderCellDef mat-header-cell mat-sort-header scope="col"> ifPattern</th>
<td *matCellDef="let dataRecord;" mat-cell>
<mat-form-field [ngStyle]="{'width.px': columnWidth[0]}" floatLabel="never">
<input (input)="resize(0, dataRecord.col1)" [(ngModel)]="dataRecord.col1"
[value]="dataRecord.col1" matInput placeholder="col1 value">
</mat-form-field>
</td>
</ng-container>
...
调整大小方法
displayedColumns: string[] = ["col1", "col2", "col3"];
minWidth: number = 64; // pixel
columnWidth: number[] = [this.minWidth, this.minWidth, this.minWidth];
resize(column_index: number, value: string) {
setTimeout(() => {
let span = document.createElement('span');
span.innerText = value;
let div = document.getElementById('case-cleaning-overview')
div?.append(span);
this.columnWidth[column_index] = Math.max(this.minWidth, span.offsetWidth);
div?.removeChild(span);
});
}
简单且唯一的模板解决方案:
<mat-form-field
[ngStyle]="{'width.ch': inputText.value.length, 'min-width.ch': 10}">
<input #inputText matInput>
</mat-form-field>
我正在尝试创建一个 input
字段,该字段至少在宽度上随用户输入的字符串长度动态扩展,甚至可能是多行。
Angular Material 2 中的 input
元素可能吗?
使用 Angular Material 2 中的 textarea
字段,我只能使用以下代码扩展高度的文本区域,而不是宽度:
<mat-form-field (keydown.enter)="onEnter()"
floatPlaceholder="never">
<textarea matInput
placeholder="Autosize textarea"
matTextareaAutosize
matAutosizeMinRows="1"
matAutosizeMaxRows="8">
</textarea>
</mat-form-field>
在 textarea
的情况下,scrollbar
应该是不可见的或被较小的替换。最重要的是,按 Enter 不应创建新行,而只会触发一个操作。
您可以使用 ngStyle 将 mat-form-field 的宽度绑定到计算值,并使用输入上的输入事件来设置该值。例如,这里有一个宽度跟随超过 64px 的文本宽度的输入:
<mat-form-field [ngStyle]="{'width.px': width}">
<input #elasticInput matInput (input)="resize()">
</mat-form-field>
<span #hiddenText style="visibility: hidden; white-space: pre;">{{elasticInput.value}}</span>
export class InputTextWidthExample {
@ViewChild('hiddenText') textEl: ElementRef;
minWidth: number = 64;
width: number = this.minWidth;
resize() {
setTimeout(() => this.width = Math.max(this.minWidth, this.textEl.nativeElement.offsetWidth));
}
}
显然,此示例使用隐藏的 span 元素来获取文本宽度,这有点 hacky。计算字符串宽度的方法肯定不止一种,包括 this.
我现在为这个问题创建了一个更合适的解决方案。在我在 jQuery 中找到完美的解决方案后,@Obsidian 添加了 corresponding JS code。我尝试将其改编为 Angular input
并提出以下内容。
我还添加了一些支持剪切和粘贴字符串的场景。
Here is a demo on StackBlitz及对应代码:
模板:
<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>
调整大小方法:
@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)
}
我需要 matInput
在 mat-table
内的动态宽度(动态大小),我尝试了几种基于 <span>
元素是不切实际的。因此,我想出了一个比较实用的解决方案:
每当数据更新时,我创建一个 <span>
元素,用更新的数据填充它,将它添加到 HTML body
(或 div
中我的情况),提取 <span>
的 offsetWidth
并立即将其从 HTML 文档中删除。在测试时,我没有观察到任何闪烁或渲染问题(尽管我认为这是可能的)。
模板
...
<!-- col1 Column -->
<ng-container matColumnDef="col1">
<th *matHeaderCellDef mat-header-cell mat-sort-header scope="col"> ifPattern</th>
<td *matCellDef="let dataRecord;" mat-cell>
<mat-form-field [ngStyle]="{'width.px': columnWidth[0]}" floatLabel="never">
<input (input)="resize(0, dataRecord.col1)" [(ngModel)]="dataRecord.col1"
[value]="dataRecord.col1" matInput placeholder="col1 value">
</mat-form-field>
</td>
</ng-container>
...
调整大小方法
displayedColumns: string[] = ["col1", "col2", "col3"];
minWidth: number = 64; // pixel
columnWidth: number[] = [this.minWidth, this.minWidth, this.minWidth];
resize(column_index: number, value: string) {
setTimeout(() => {
let span = document.createElement('span');
span.innerText = value;
let div = document.getElementById('case-cleaning-overview')
div?.append(span);
this.columnWidth[column_index] = Math.max(this.minWidth, span.offsetWidth);
div?.removeChild(span);
});
}
简单且唯一的模板解决方案:
<mat-form-field
[ngStyle]="{'width.ch': inputText.value.length, 'min-width.ch': 10}">
<input #inputText matInput>
</mat-form-field>