angular 15 实现按下确认键,焦点移动到下一个表单或提交表单

Fork Me On Github

angular 15 实现按下确认键,焦点移动到下一个表单或提交表单

需求:登录界面,输入账户后,按下回车键,焦点移动到密码输入框,再次按下回车键,直接提交表单

实现方法

ts
                                                                                                                                    
import { Directive, ElementRef, HostListener, Input, OnDestroy, OnInit } from '@angular/core';


@Directive({
    selector: '[appFocusNext]'
})
export class FocusNextDirective implements OnInit, OnDestroy {

    static InputItems: FocusNextDirective[] = [];

    /**
     * 分组
     */
    @Input() public appFocusNext: any = 0;
    /**
     * 排序,越大越往后
     */
    @Input() public order = 0;

    constructor(
        private elementRef: ElementRef,
    ) { }

    @HostListener('keydown', ['$event'])
    onKeydown(e: KeyboardEvent) {
        if (e.key !== 'Enter') {
            return;
        }
        e.preventDefault();
        e.stopPropagation();
        FocusNextDirective.FocusNext(this);
    }


    ngOnInit(): void {
        FocusNextDirective.Add(this);
    }

    ngOnDestroy(): void {
        FocusNextDirective.Remove(this);
    }

    /**
     * 移动焦点到当前项
     * @returns 
     */
    public focus() {
        if (!this.elementRef.nativeElement) {
            return;
        }
        const element = this.elementRef.nativeElement;
        const tagName = element.tagName.toLocaleLowerCase();
        if (tagName === 'textarea' || tagName === 'select') {
            (element as HTMLTextAreaElement).focus();
            return;
        }
        if (tagName === 'input') {
            const type = (element as HTMLInputElement).type.toLocaleLowerCase();
            console.log(type);

            if (type === 'button' || type === 'submit' || type === 'reset') {
                element.click();
                return;
            }
            (element as HTMLInputElement).focus();
            return;
        }
        if (tagName === 'form') {
            (element as HTMLFormElement).submit();
            return;
        }
        element.click();
    }

    /**
     * 注册到可操作项
     * @param item 
     * @returns 
     */
    private static Add(item: FocusNextDirective) {
        if (this.InputItems.indexOf(item) >= 0) {
            return;
        }
        this.InputItems.push(item);
    }

    /**
     * 移除当前
     * @param item 
     */
    private static Remove(item: FocusNextDirective) {
        const i = this.InputItems.indexOf(item);
        if (i >= 0) {
            this.InputItems.splice(i, 1);
        }
    }

    /**
     * 根据当前触发,移动焦点到下一项
     * @param source 
     */
    private static FocusNext(source: FocusNextDirective) {
        let found = false;
        let next: FocusNextDirective = undefined;
        for (const item of this.InputItems) {
            if (item.appFocusNext !== source.appFocusNext) {
                continue;
            }
            if (item === source) {
                found = true;
                continue;
            }
            if (item.order < source.order || (!found && item.order === source.order)) {
                continue;
            }
            if (item.order === source.order && found) {
                next = item;
                break;
            }
            if (!next) {
                next = item;
                continue;
            }
            if (next.order > item.order) {
                next = item;
                continue;
            }
        }
        next?.focus();
    }
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132

使用方法

html
         

<input appFocusNext>
<input appFocusNext>
<button appFocusNext>提交</button>


<input appFocusNext="1">
<button appFocusNext="1" [order]="1">提交</button>
<input appFocusNext="1">
123456789

参数说明

appFocusNext 属性值是作为分组使用

order 作为排序用,数字越大排在后面,最后触发,默认按照初始化顺序

缺陷或不足

  1. 自定义的组件,暂时没有找到办法获取对象,只获取到了HTMLElement
  2. 不会验证表单的内容
  3. 不会自动触发上层表单
点击查看全文
标签: angular
0 96 0
在 angular 项目中实现对页面的访问控制
使用ng-template 显示tree结构数据
使用 ViewContainerRef.createComponent 替代 ComponentFactoryResolver
angular 12使用 KaTex 显示 AsciiMath 格式的公式
ng-deep 使用