angular - 如何以 Angular 方式将焦点转移到表单元素上

标签 angular

目标

  • 我有一个包含一些输入元素(el1、el2 ...)的表单
  • el1 可能会关注开始或不关注
  • 当 keydown 事件触发时,执行以下操作:
    • 如果所有输入元素都没有焦点,则将焦点设置到第一个非空元素
    • 如果任何输入元素获得焦点,检查是否按下了回车键,是否移动到下一个任意元素
    • 在任何其他情况下,让 key 按照它的意图行事

我当前的代码

表单.组件.html

<form>
      <input type="text" class="form-control" id="el1" name="el1"
             required focus
             [(ngModel)]="el1" #el1
             (keydown)="processEl1KeyDown($event)"
      >
      <input type="text" class="form-control" id="el2" name="el2"
             required
             [(ngModel)]="el2" #el2
             (keydown)="processEl2KeyDown($event)"
      >
</form>

表单.component.ts

@Component({
    selector: 'my-form',
    templateUrl: 'app/form.component.html'
})
export class FormComponent {

    constructor(private renderer:Renderer) {
    }

    el1: string;
    el2: string

    @ViewChild("el1")
    el1El: ElementRef;

    @ViewChild("el2")
    el2El: ElementRef;


    @HostListener('document:keydown', ['$event'])
    handleKeyboardEvent(event: KeyboardEvent) {
        if (!this.el1) {
            this.setFocus(this.el1El);
        } else {
            this.setFocus(this.el2El);
        }
    }


    processEl1KeyDown(event: KeyboardEvent) {
        event.stopPropagation();
        if (event.keyCode == 13) {
            this.setFocus(this.el2El);
        }
    }


    processEl2KeyDown(event: KeyboardEvent) {
        event.stopPropagation();
        if (event.keyCode == 13) {
            this.submitForm();
        }
    }

    submitForm() {
        console.log("submit form");
    }

    setFocus(element: ElementRef) {
        this.renderer.invokeElementMethod(element.nativeElement, 'focus');
    }
}

问题

  1. 如何从 FormComponent 类中获取焦点元素的模板变量名称(例如#el1、#el2)? document.activeElement返回 DOM 元素。
  2. 我可以从 DOM 中获取 Angular2 对象吗?类似 ElementRef.create('<div></div>') 的东西
  3. 如果我想将任意字符串传递给我的 setFocus('el1')函数,我如何从中构建 ElementRef?我可以使用 @ViewChild装饰器,但我需要一些可以在运行时定义的东西?像新的一样ViewChild('el1')
  4. 还有什么方法可以更“Angular2”来解决我的问题?使用此答案中提到的 BehaviorSubject - Delegation: EventEmitter or Observable in Angular2

编辑

可能提问的不够清楚。总结一下:如果我有 n 个输入元素(el1、el2 ... eln),我如何知道模块中哪个元素具有焦点(可能通过模板变量),然后将焦点移动到不同的元素(通过字符串,哪个再次对应于另一个模板变量)。我想我正在查看 angular.element 等效项 - Get ComponentRef from DOM element ,但我认为这可能不是正确的方法。

最佳答案

我认为焦点指令可能会解决您列出的大部分问题。我遇到了类似的问题并编写了这个指令来解决它们:

@Directive
({
    selector: '[hasFocus]'
})

export class HasFocusDirective
{
    @Input("hasFocus") hasFocus: boolean;
    constructor(private elementRef: ElementRef) {}

    ngAfterViewInit()
    {
        if (this.hasFocus)
        {
            this.elementRef.nativeElement.focus();
        }
    }

    ngOnChanges(changes: SimpleChanges)
    {
        if (changes["hasFocus"] && changes["hasFocus"].currentValue === true)
        {
            this.elementRef.nativeElement.focus();
        }
    }
}

[hasFocus] 是一个 bool 值,您可以使用任何 bool 表达式来动态控制使用它的元素的焦点。

关于angular - 如何以 Angular 方式将焦点转移到表单元素上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39028334/

相关文章:

angular - ng-bootstrap: ngb-progressbar 自定义背景颜色

Angular 2 - 子模块路由和嵌套 <router-outlet>

javascript - 使用 ng new 创建一个新的 Angular 项目

javascript - 当我在 Angular 6 中将其设置为可编辑内容时,如何将焦点设置在该元素上?

angular - 在第一个值发射后,主体从数组中失去观察者。 Angular RouteReuseStrategy 表编辑表单通信

angular - 许多元素上的 ngClass 使网站速度非常慢

angular - 如何以最有效的方式提取ViewContainerRef和ComponentRef?

angular - 禁用 Angular 默认键值管道排序

javascript - Angular printjs : ERROR TypeError: Object(. ..) 不是函数

当 mat-expansion-panel-header 在子组件中时 CSS 不适用