【问题标题】:*ngIf with focus directive*ngIf 带焦点指令
【发布时间】:2017-08-26 02:46:42
【问题描述】:

在我的应用程序中,我尝试放置一个按钮来显示/隐藏带有 boolean 组件属性的 input 字段。如果按钮显示input,则焦点应设置在input。但这似乎不起作用。如果我删除 *ngIf,焦点指令可以正常工作。

我创建了一个 plunker 来表达我的意思。描述我的问题有点困难。

组件中的 HTML:

<input *ngIf="filterShow.options"
       [focus]="filterFocus.options"
       [(ngModel)]="filter.options">

<button type="button"
        (click)="setShowFilter('options')">
  focus
</button>

setShowFilter()方法:

private setShowFilter(filter: string) {
  this.filterShow[filter] = !this.filterShow[filter];

  /* reset filter */
  this.filter[filter] = "";

  this.filterFocus[filter].emit(true);
}

focus.directive.ts:

@Directive({
  selector: '[focus]'
})
export class FocusDirective implements OnInit {

  @Input('focus') focusEvent: EventEmitter<boolean>;

  constructor(private elementRef : ElementRef,
              private renderer   : Renderer   ) { }

  ngOnInit() {
    this.focusEvent.subscribe(event => {
      this.renderer
        .invokeElementMethod(this.elementRef.nativeElement, 'focus', []);
    });
  }
}

【问题讨论】:

    标签: angular input focus angular-ng-if


    【解决方案1】:

    EventEmitters 用于@Outputs,而不用于@Inputs。尝试这样的事情:

    @Directive({
      selector: '[focus]'
    })
    export class FocusDirective implements OnChanges {
    
      @Input('focus') focus: boolean;
    
      constructor(private elementRef : ElementRef,
                  private renderer   : Renderer   ) { }
    
      ngOnChanges() {
        if (this.focus) {
          this.renderer
            .invokeElementMethod(this.elementRef.nativeElement, 'focus', []);
        }
      }
    }
    

    【讨论】:

    • 您错误地使用了事件发射器。它们用于子-> 父通信,而不是用于父-> 子。我发布的内容对我有用:plnkr.co/edit/YtaRtA0e5L6ewxq7uCH9?p=preview
    • Renderer 和它的 .invokeElementMethod() 方法在这个时间点已被弃用。现在可以直接拨打this.elementRef.nativeElement.focus()了。
    【解决方案2】:

    大多数时候,它不起作用,因为焦点事件后面跟着其他事件。所以元素失去了焦点。我们需要使用setTimeout 将其放在任务调度程序队列的末尾:

    import { Directive, OnChanges, Input, ElementRef } from "@angular/core";
    
    @Directive({
      selector: '[focus]'
    })
    export class FocusDirective implements OnChanges {
      @Input('focus') focus: boolean;
    
      constructor(private elementRef : ElementRef) { }
    
      ngOnChanges() {
        if (this.focus) {
          setTimeout(() => { this.elementRef.nativeElement.focus(); }, 0);      
        }
      }
    }
    

    【讨论】:

      【解决方案3】:

      无需使用指令即可实现此目的的一种更简洁的方法是使用 &lt;label&gt; 而不是 &lt;button&gt; 并使用 css 将其设置为像按钮一样的样式。例如,

      <label for="myInput"></label> <input id="myInput"></input>

      这样即使*ngIf 存在,您也可以实现焦点,因为&lt;input&gt; 现在绑定到&lt;label&gt;Also, Angular2 documentation website warns about the use of ElementRef because of the security vulnerability it poses.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-04-25
        • 1970-01-01
        • 2021-05-15
        • 1970-01-01
        • 1970-01-01
        • 2018-12-30
        • 1970-01-01
        相关资源
        最近更新 更多