为什么使用* ngIf时模板局部变量在模板中不可用?

米卡·费利克斯

第1部分:使用* ngIf时,“#test”未定义

当引用一个可以隐藏/“销毁”的输入时(因为*ngIf使用了,并且某些元素被销毁了),即使元素存在于以下变量中,通过井号标签语法创建的局部变量##test在下面的示例中)也不起作用。这一页。

代码是:

@Component({
    selector: 'my-app',
    template: `<h1>My First Angular 2 App</h1>
    <button (click)="focusOther(test)">test</button>
    <input #test *ngIf="boolValue" >
    `
})
export class AppComponent { 

  private isVisible = false;

  focusOther(testElement){
    this.isVisible = true;
    alert(testElement);
    testElement.focus();
  }

}

警报显示undefined,因为没有任何内容传递给该功能。

有解决方案可以使其正常工作吗?我的目标是关注将要创建的元素。

马克·拉杰科克(Mark Rajcok)给出的解决方案:使用afterViewInit编写一条指令,该指令使用elementRef并在该元素上调用.focus()。

有关第1部分的工作版本,请参阅此插件:http ://plnkr.co/edit/JmBBHMo1hXLe4jrbpVdv?p=preview

第2部分如何在初始创建后重新关注该元素

解决了“创建后聚焦”的问题后,我需要一种重新聚焦组件的方法,例如在“ test.focus()”中(其中#test是输入的局部变量名称,但不能就像我之前演示的那样使用)。

Mark Rajcok提供的多种解决方案

马克·拉杰科克

至于焦点问题的解决方案,您可以创建一个属性指令focusMe

import {Component, Directive, ElementRef} from 'angular2/core';
@Directive({
  selector: '[focusMe]'
})
export class FocusDirective {
  constructor(private el: ElementRef) {}
  ngAfterViewInit() {
    this.el.nativeElement.focus();
  }
}
@Component({
    selector: 'my-app',
    directives: [FocusDirective],
    template: `<h1>My First Angular 2 App</h1>
      <button (click)="toggle()">toggle</button>
      <input focusMe *ngIf="isVisible">
    `
})
export class AppComponent { 
  constructor() { console.clear(); }
  private isVisible = false;
  toggle() {
    this.isVisible = !this.isVisible;
  }
}

Plunker

更新1:为重新对焦功能添加解决方案:

import {Component, Directive, ElementRef, Input} from 'angular2/core';

@Directive({
  selector: '[focusMe]'
})
export class FocusMe {
    @Input('focusMe') hasFocus: boolean;
    constructor(private elementRef: ElementRef) {}
    ngAfterViewInit() {
      this.elementRef.nativeElement.focus();
    }
    ngOnChanges(changes) {
      //console.log(changes);
      if(changes.hasFocus && changes.hasFocus.currentValue === true) {
        this.elementRef.nativeElement.focus();
      }
    }
}
@Component({
    selector: 'my-app',
    template: `<h1>My First Angular 2 App</h1>
    <button (click)="showInput()">Make it visible</button>
    <input *ngIf="inputIsVisible" [focusMe]="inputHasFocus">
    <button (click)="focusInput()" *ngIf="inputIsVisible">Focus it</button>
    `,
    directives:[FocusMe]
})
export class AppComponent {
  private inputIsVisible = false;
  private inputHasFocus = false;
  constructor() { console.clear(); }
  showInput() {
    this.inputIsVisible = true;
  }
  focusInput() {
    this.inputHasFocus = true;
    setTimeout(() => this.inputHasFocus = false, 50);
  }
}

Plunker

setTimeout()将焦点属性重置为的另一种方法是false在FocusDirective上创建事件/输出属性,并emit()focus()调用创建事件然后,AppComponent将侦听该事件并重置focus属性。

更新2:这是使用ViewChild添加重新对焦功能的另一种/更好的方法。我们不需要以这种方式跟踪焦点状态,也不需要在FocusMe指令上使用input属性。

import {Component, Directive, ElementRef, Input, ViewChild} from 'angular2/core';

@Directive({
  selector: '[focusMe]'
})
export class FocusMe {
    constructor(private elementRef: ElementRef) {}
    ngAfterViewInit() {
      // set focus when element first appears
      this.setFocus();
    }
    setFocus() {
      this.elementRef.nativeElement.focus();
    }
}
@Component({
    selector: 'my-app',
    template: `<h1>My First Angular 2 App</h1>
    <button (click)="showInput()">Make it visible</button>
    <input *ngIf="inputIsVisible" focusMe>
    <button (click)="focusInput()" *ngIf="inputIsVisible">Focus it</button>
    `,
    directives:[FocusMe]
})
export class AppComponent {
  @ViewChild(FocusMe) child;
  private inputIsVisible = false;
  constructor() { console.clear(); }
  showInput() {
    this.inputIsVisible = true;
  }
  focusInput() {
    this.child.setFocus();
  }
}

Plunker

更新3:这是另一种不需要指令的替代方法,该指令仍然使用ViewChild,但是我们通过本地模板变量而不是属性指令访问子级(感谢@alexpods作为提示):

import {Component, ViewChild, NgZone} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: `<h1>Focus test</h1>
    <button (click)="showInput()">Make it visible</button>
    <input #input1 *ngIf="input1IsVisible">
    <button (click)="focusInput1()" *ngIf="input1IsVisible">Focus it</button>
    `,
})
export class AppComponent {
  @ViewChild('input1') input1ElementRef;
  private input1IsVisible = false;
  constructor(private _ngZone: NgZone) { console.clear(); }
  showInput() {
    this.input1IsVisible = true;
    // Give ngIf a chance to render the <input>.
    // Then set the focus, but do this outside the Angualar zone to be efficient.
    // There is no need to run change detection after setTimeout() runs,
    // since we're only focusing an element.
    this._ngZone.runOutsideAngular(() => { 
      setTimeout(() => this.focusInput1(), 0);
   });
  }
  setFocus(elementRef) {
    elementRef.nativeElement.focus();
  }
  ngDoCheck() {
    // if you remove the ngZone stuff above, you'll see
    // this log 3 times instead of 1 when you click the
    // "Make it visible" button.
    console.log('doCheck');
  }
  focusInput1() {
    this.setFocus(this.input1ElementRef);
  }
}

Plunker

更新4:我更新了更新3中的代码以使用NgZone,这样我们就不会导致Angular的更改检测算法在setTimeout()完成后运行(有关更改检测的更多信息,请参见此答案)。

更新5:我更新了上述插件中的代码,以使用Renderer使其网络工作者安全。不建议focus()直接访问nativeElement

focusInput1() {
  this._renderer.invokeElementMethod(
    this.input1ElementRef.nativeElement, 'focus', []);
}

我从这个问题中学到很多东西。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么在此示例中变量范围不可用

来自分类Dev

为什么变量不可用?

来自分类Dev

在Angular 2中使用* ngFor访问HTML模板中的局部变量

来自分类Dev

AngularJS指令:引用模板中使用的外部HTML文件中的局部变量

来自分类Dev

观看未使用的局部变量是不可能的吗?为什么?

来自分类Dev

为什么我使用框架收到不可用的声明

来自分类Dev

为什么在React功能组件中使用局部变量?

来自分类Dev

在程序中使用非类型模板参数而未分配局部变量时出现意外结果?

来自分类Dev

为什么在 if 条件下外部变量不可用

来自分类Dev

为什么变量值在循环外不可用

来自分类Dev

为什么使用任务并行库任务时httpcontext对象不可用?

来自分类Dev

不使用局部变量时为什么会获得EXC BAD ACCESS?

来自分类Dev

在类构造函数中,为什么“这是必需的”?为什么我不能使用局部变量?

来自分类Dev

为什么在Node.js中执行SQL查询后不能使用局部变量?

来自分类Dev

为什么 Groovy 的日期扩展在 Micronaut 中不可用?

来自分类Dev

为什么隐式类中的函数不可用?

来自分类Python

为什么是Python 3.6.1。pyenv中不可用?

来自分类Dev

为什么 SparkSession 在 Spark2.3 中不可用

来自分类Dev

为什么别名在 /etc/profile 中不可用?

来自分类Dev

为什么NPM在Docker容器中不可用

来自分类Dev

为什么原型在简单的JavaScript对象中不可用

来自分类Dev

为什么无符号整数在PostgreSQL中不可用?

来自分类Java

为什么@HeadMapping在Spring MVC中不可用?

来自分类Dev

为什么以及何时malloc()在C中不可用?

来自分类Dev

为什么“共享按钮”在Ubuntu One中不可用?

来自分类Dev

为什么 vundle 在 apt 中不可用?

来自分类Java

为什么局部变量在Java中是线程安全的

来自分类Dev

为什么局部变量会在Python中循环

来自分类Dev

为什么lambda对象中的局部变量是const?

Related 相关文章

  1. 1

    为什么在此示例中变量范围不可用

  2. 2

    为什么变量不可用?

  3. 3

    在Angular 2中使用* ngFor访问HTML模板中的局部变量

  4. 4

    AngularJS指令:引用模板中使用的外部HTML文件中的局部变量

  5. 5

    观看未使用的局部变量是不可能的吗?为什么?

  6. 6

    为什么我使用框架收到不可用的声明

  7. 7

    为什么在React功能组件中使用局部变量?

  8. 8

    在程序中使用非类型模板参数而未分配局部变量时出现意外结果?

  9. 9

    为什么在 if 条件下外部变量不可用

  10. 10

    为什么变量值在循环外不可用

  11. 11

    为什么使用任务并行库任务时httpcontext对象不可用?

  12. 12

    不使用局部变量时为什么会获得EXC BAD ACCESS?

  13. 13

    在类构造函数中,为什么“这是必需的”?为什么我不能使用局部变量?

  14. 14

    为什么在Node.js中执行SQL查询后不能使用局部变量?

  15. 15

    为什么 Groovy 的日期扩展在 Micronaut 中不可用?

  16. 16

    为什么隐式类中的函数不可用?

  17. 17

    为什么是Python 3.6.1。pyenv中不可用?

  18. 18

    为什么 SparkSession 在 Spark2.3 中不可用

  19. 19

    为什么别名在 /etc/profile 中不可用?

  20. 20

    为什么NPM在Docker容器中不可用

  21. 21

    为什么原型在简单的JavaScript对象中不可用

  22. 22

    为什么无符号整数在PostgreSQL中不可用?

  23. 23

    为什么@HeadMapping在Spring MVC中不可用?

  24. 24

    为什么以及何时malloc()在C中不可用?

  25. 25

    为什么“共享按钮”在Ubuntu One中不可用?

  26. 26

    为什么 vundle 在 apt 中不可用?

  27. 27

    为什么局部变量在Java中是线程安全的

  28. 28

    为什么局部变量会在Python中循环

  29. 29

    为什么lambda对象中的局部变量是const?

热门标签

归档