将输入宽度动态扩展到字符串的长度

时间:2018-03-19 10:18:10

标签: css angular angular5 angular-material2 angular-animations

我正在尝试创建一个input字段,该字段至少在宽度上以用户输入的字符串的长度动态扩展,甚至可能是多行。 在Angular Material 2中使用input元素是否可能?

使用Angular Material 2中的textarea字段,我只设法使用以下代码扩展textarea的高度,而不是宽度:

<mat-form-field (keydown.enter)="onEnter()" 
                floatPlaceholder="never">
  <textarea matInput 
            placeholder="Autosize textarea" 
            matTextareaAutosize
            matAutosizeMinRows="1" 
            matAutosizeMaxRows="8">
  </textarea>
</mat-form-field>

also on StackBlitz

如果textarea scrollbar应该不可见或被较小的[DataContract(Namespace ="")] public class UPDATED_ACCOUNT_DETAILS_REQUEST : BASENEW { [DataMember(Order =3)] public string MSISDN { get; set; } [DataMember(Order = 4)] public string IMSI { get; set; } [DataMember(Order = 5)] public string ICC_ID { get; set; } } 取代。最重要的是按 Enter 不应创建新行,而只触发操作。

3 个答案:

答案 0 :(得分:2)

您可以使用ngStyle将mat-form-field的宽度绑定到计算值,并使用输入上的input事件来设置该值。例如,这是一个输入,其宽度跟随文本宽度超过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

Here is the example on Stackblitz

答案 1 :(得分:1)

我现在为这个问题创建了一个更合适的解决方案。在我发现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)
}

答案 2 :(得分:0)

我需要 matInput(动态大小)内的 mat-table 的动态宽度,并且我尝试了几种基于 G.Tranter's solution 的方法。但是,根据呈现的表格单元格查看动态数量的 <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);
    });
  }