【问题标题】:Set focus on dynamically created input on Angular将焦点放在 Angular 上动态创建的输入上
【发布时间】:2020-07-08 01:54:09
【问题描述】:

我正在使用 *ngFor 动态创建输入。所以,我想在最后创建的输入上设置 focus。有人可以帮我吗?

这是我的模板代码:

                <div class="col-6">
              <mat-card class="dataItens">
                <mat-card-header>
                  <mat-card-title>Itens de dados</mat-card-title>
                </mat-card-header>
                <mat-card-content>
                  <section *ngFor="let dataItem of elementaryProcess.dataItens; let i = index;">
                    <mat-form-field class="input-dataItens">
                      <input matInput [(ngModel)]="dataItem.name" name="dataItem{{ i }}" id="dataItem{{ i }}"
                             autocomplete="off"
                             [ngModelOptions]="{standalone: true}" class="input-dataItens"
                             (keyup.arrowDown)="dataItemOnKeyUp()"/>
                    </mat-form-field>
                    <button type="button" mat-icon-button (click)="removeDataItem(i)">
                      <mat-icon>delete</mat-icon>
                    </button>
                  </section>
                </mat-card-content>
                <mat-card-actions>
                  <form>
                    <!-- Add button -->
                    <button mat-stroked-button color="primary" type="button" (click)="addDataItem()">Adicionar
                    </button>
                    <!-- ngFor code -->
                  </form>
                </mat-card-actions>
              </mat-card>
            </div>

这是我用来添加输入的函数:

  addDataItem() {
    this.elementaryProcess.dataItens.push(new DataItem());
  }

【问题讨论】:

    标签: angular


    【解决方案1】:

    使用 ViewChildren 和 ViewChildren.changes。看到这个SO

    我更新了 stackblitz 以使用箭头键聚焦。比创建函数还简单

    @ViewChildren('input') inputs: QueryList<ElementRef> //<--here declare our "inputs"
    focusElement(index:number){
        const input=this.inputs.find((x,i)=>i==index)
        if (input)
          input.nativeElement.focus()
      }
    

    在 .html 中,我们使用 keydown.arrowUp 和 keydown.arrowDown

    <p *ngFor="let el of elements;let i=index">
      <input #input (keydown.arrowUp)="focusElement(i-1)"
                    (keydown.arrowDown)="focusElement(i+1)" >
    </p>
    

    已更新,正如下面的 Victor cmets,当您没有物品时会出现问题。这是因为我忘记检查是否有输入。所以,当订阅inputs.changes我们需要检查它

    this.inputs.changes.pipe(takeWhile(()=>this.alive)).subscribe(() => {
      if (this.inputs.length)  //<--add this "if"
        this.inputs.last.nativeElement.focus()
    })
    

    【讨论】:

    • 这是我采用的解决方案,但它部分有效。当我删除所有组件并再次插入第一个组件时,它会停止聚焦。这里举个例子:stackblitz.com/edit/set-focus-example
    • @VictorVidigalRibeiro,我更新了答案,问题是我没有检查是否有元素,所以,如果没有元素,Angular 会给出错误并且应用程序崩溃,谢谢广告!
    • 我不知道“更新”的代码应该放在哪里。请您创建一个示例或重新编写代码以使其清晰吗?
    • 如果你看到 stackblitz stackblitz.com/edit/…,在 ngAferViewInit 中我订阅了“this.inputs.changes”,“更新的代码”是我添加的if (this.inputs.length)
    【解决方案2】:

    有多种方法可以做到这一点,但这段代码只是使用模板

    你可以像这样使用 ngFor last 来做到这一点

    <ng-container *ngFor="let item of [1,2,3]; last as isLast" >
    
    <input *ngIf="!isLast"type="text">
    
    <ng-container *ngIf="isLast" >
       <input type="text" #lastOne>
       {{lastOne.focus()}}
    </ng-container>
    </ng-container>
    

    这样的另一种方法。

    <ng-container *ngFor="let item of [1,2,3]" >
    
    <input  type="text" #lastOne>
    
    {{lastOne.focus()}}
    </ng-container>
    

    随意选择

    https://stackblitz.com/edit/angular-7-master-g3qsmt?file=src%2Fapp%2Fapp.component.html

    【讨论】:

    • 使用插值来执行函数是一个绝妙的解决方法,但我认为有一种“更规范的方式”(见我的评论)
    • 是的,这是我想到的第一件事。但经过一番搜索,我找到了这个。
    • 在第一个解决方案中,我应该复制 元素。我的 很大:
    • 第二种解决方案不起作用。它将焦点放在所有插入的输入上。
    • 可能取决于我发布时它正在工作的角度版本 bcs
    猜你喜欢
    • 2017-05-15
    • 2018-03-25
    • 2023-03-08
    • 1970-01-01
    • 2017-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多