簡體   English   中英

如何在Angular Material中將tab鍵設為回車鍵?

[英]How to make tab key as enter key in Angular Material?

這是我的角度材料自動完成代碼

<input type="search" id="setId" name="setId" [attr.list]='collectionType' [(ngModel)]="selValue" class="text-box"
  placeholder="--Select--" (focus)="ValidateParent()" (keyup.tab)="test()" (keyup)="EmitValues($event)" [id]="setId"
  [matAutocomplete]="auto" [title]="selValue" [placeholder]='WaterMarkText'>


<div [hidden]="IsCascading">
  <mat-autocomplete [id]="collectionType" #auto="matAutocomplete" (optionSelected)='onChange($event)'>
    <mat-option *ngFor="let items of codeList" [value]="items.text" [attr.data-text]='items.text' [id]="items.value">
      {{items.text}}
    </mat-option>
  </mat-autocomplete>
</div>

角材料在tab選擇方面存在問題。例如,單擊tab按鈕時,材料自動完成無法選擇值。 但是在單擊enter按鈕時它正在工作。 所以我需要手動覆蓋tab鍵事件上的enter鍵事件。 怎么可能?

改進我的評論,並根據回復我們可以創建一個指令

import {
    Directive,
    AfterViewInit,
    OnDestroy,
    Optional
} from '@angular/core';
import {
    MatAutocompleteTrigger
} from '@angular/material';


@Directive({
    selector: '[tab-directive]'
})
export class TabDirective implements AfterViewInit, OnDestroy {
    observable: any;
    constructor(@Optional() private autoTrigger: MatAutocompleteTrigger) {}
    ngAfterViewInit() {
        this.observable = this.autoTrigger.panelClosingActions.subscribe(x => {
            if (this.autoTrigger.activeOption) {
                this.autoTrigger.writeValue(this.autoTrigger.activeOption.value)
            }
        })
    }
    ngOnDestroy() {
        this.observable.unsubscribe();
    }
}

你用:

<input tab-directive type="text" matInput [formControl]="myControl" 
      [matAutocomplete]="auto" >

(見堆棧閃電戰

更新我們只能控制tab.key,否則你總是關閉,你得到選定的值,所以

@Directive({
    selector: '[tab-directive]'
})
export class TabDirective {
    observable: any;
    constructor(@Optional() private autoTrigger: MatAutocompleteTrigger) {}

    @HostListener('keydown.tab', ['$event.target']) onBlur() {
        if (this.autoTrigger.activeOption) {
            this.autoTrigger.writeValue(this.autoTrigger.activeOption.value)
        }
    }

}

(見一個新的堆棧閃電戰)

更新 2我不相信這個答案有這么多贊成票,因為它是錯誤的。 正如@Andrew allen 評論的那樣,該指令不會更新控件。 好吧,已經晚了,但我嘗試解決。 一種選擇是使用

this.autoTrigger._onChange(this.autoTrigger.activeOption.value)

另一個想法是注入 ngControl,所以

constructor(@Optional() private autoTrigger: MatAutocompleteTrigger,
    @Optional() private control: NgControl) {}
ngAfterViewInit() {
    this.observable = this.autoTrigger.panelClosingActions.subscribe(x => {
        if (this.autoTrigger.activeOption) {
            const value = this.autoTrigger.activeOption.value;
            if (this.control)
                this.control.control.setValue(value, {
                    emit: false
                });
            this.autoTrigger.writeValue(value);
        }
    })
}

我參加聚會有點晚了; 因此,Eliseo 的回答有一個令人討厭的問題:即使用戶已經通過單擊鼠標從面板中選擇了不同的選項,它也會自動完成。 我最終想出的解決方法根本不是直截了當的。

    /**
     * Selects currently active item on TAB
     * @example
     * <input vxTabActiveOption [matAutocomplete]="matAutocomplate">
     * <mat-autocomplete #matAutocomplate="matAutocomplete" autoActiveFirstOption>
     */
    @Directive({ selector: '[vxTabActiveOption]' })
    export class TabActiveOptionDirective implements AfterViewInit, OnDestroy {
      private readonly destroy$ = new Subject<never>();
    
      /**
       * Whether or not the autocomplete panel was open before the event
       */
      private panelOpen = false;
    
      constructor(
        private autoTrigger: MatAutocompleteTrigger,
        private control: NgControl
      ) { }
    
      ngAfterViewInit() {
        const autocomplete = this.autoTrigger.autocomplete;
        merge(
          autocomplete.opened.pipe(map(() => true)),
          autocomplete.closed.pipe(map(() => false))
        ).pipe(
          takeUntil(this.destroy$),
          delay(0)
        ).subscribe(value => this.panelOpen = value);
      }

      @HostListener('keydown.tab')
      onBlur() {
        if (this.panelOpen && this.autoTrigger.activeOption) {
          const value = this.autoTrigger.activeOption.value;
          this.control.control.setValue(value, { emit: false });
          this.autoTrigger.writeValue(value);
        }
      }
    
      ngOnDestroy() {
        this.destroy$.next();
        this.destroy$.complete();
      }
    }

是的,我知道這是一個老問題,但是有一個更好的方法是使用像這樣的指令

@Directive({ selector: '[tab-selected]' })
export class TabSelected implements AfterViewInit {
  constructor(private auto: MatAutocomplete) {}
  ngAfterViewInit() {
    this.auto._keyManager.onKeydown = (event: KeyboardEvent) => {
      switch (event.keyCode) {
        case TAB:
          if (this.auto.isOpen) {
            const option = this.auto.options.find(x => x.active);
            if (option) {
              option.select();
              event.preventDefault();
              return;
            }
          }
          this.auto._keyManager.tabOut.next();
          break;
        case DOWN_ARROW:
          this.auto._keyManager.setNextItemActive();
          break;

        case UP_ARROW:
          this.auto._keyManager.setPreviousItemActive();
          break;
      }
    };
  }
}

你用像

<mat-form-field class="example-full-width" appearance="fill">
  <mat-label>Number</mat-label>
  <input type="text"
         placeholder="Pick one"
         aria-label="Number"
         matInput
         [formControl]="myControl"
         [matAutocomplete]="auto">
  <mat-autocomplete tab-selected #auto="matAutocomplete"
  autoActiveFirstOption >
    <mat-option  *ngFor="let option of filteredOptions | async" [value]="option">
      {{option}}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

你可以在這個堆棧閃電戰中工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM