簡體   English   中英

角材料自動完成力選擇

[英]Angular Material Autocomplete force selection

在我的 angular 5 應用程序中,我有一些 matAutocomplete,但我想強制選擇一個建議,所以我遵循這種方法: stackblitz但出於某種原因,我遇到了一個問題:

無法讀取 CustomerDetailComponent.countryClosingActions (customer-detail.component.ts:199) at CustomerDetailComponent.ngAfterViewInit 處未定義的屬性“panelClosingActions”

我有多個 matAutocomplete,但只有這個有問題。 (有關此方法的信息在這里github

html

<mat-form-field>
    <input matInput #nation placeholder="{{'customer.detail.labels.country'
      | translate }}" required [matAutocomplete]="tdAuto" name="country"  
      #count="ngModel" [(ngModel)]="selected.country"
      (ngModelChange)="searchCountry($event)">
        <mat-autocomplete #tdAuto="matAutocomplete" [displayWith]="displayFn">
          <mat-option (onSelectionChange)="setCountry(country)" *ngFor="let country of countries" [value]="country">
             <div class="row">
               <img src="assets/img/flags24/{{country.alpha2Code | lowercase}}.png" />
                  <span>{{country.name}} ({{country.alpha2Code}})</span>
             </div>
         </mat-option>
        </mat-autocomplete>
    </mat-form-field>

組件

@ViewChild('nation', { read: MatAutocompleteTrigger }) trigger: MatAutocompleteTrigger;
  subscription: Subscription;


ngAfterViewInit() {
    this.countryClosingActions();
  }

  private countryClosingActions(): void {
    if (this.subscription && !this.subscription.closed) {
      this.subscription.unsubscribe();
    }

    this.subscription = this.trigger.panelClosingActions
      .subscribe(e => {
        console.log('closing')
        if (!e || !e.source) {
          this.selected.country = null;
          this.selfCountry = null;
        }
      },
      err => this.countryClosingActions(),
      () => this.countryClosingActions());
  }

使用模糊事件和 matAutocomplete 輸出事件(optionSelected),我們可以強制用戶選擇選項。

<mat-form-field class="example-full-width">
  <input type="text" placeholder="Country*" matInput formControlName="country" [matAutocomplete]="countryAutoList" (blur)="checkCountry()">
  <mat-autocomplete autoActiveFirstOption #countryAutoList="matAutocomplete" (optionSelected)="countryClick($event)">
    <mat-option *ngFor="let item of countryList" [value]="item.Name">{{item.Name}}</mat-option>
  </mat-autocomplete>
</mat-form-field>

ts 文件函數

countryClick(event: any) {
  this.selectedCountry = event.option.value;
}

checkCountry() {
 setTimeout(()=> {
  if (!this.selectedCountry || this.selectedCountry !== this.signatureFormGroup.controls['country'].value) {
    this.signatureFormGroup.controls['country'].setValue(null);
    this.selectedCountry = '';
  }
 }, 1000);
}

根據您的要求,您始終可以使用 setTimeout 窗口函數延遲您在 blur 或 optionSelect 事件中調用的函數。

setTimeout(()=> { 
// function contents
}, 1000);

我發現很有幫助:

private subscribeToClosingActions(): void {
if (this.subscription && !this.subscription.closed) {
  this.subscription.unsubscribe();
}

this.subscription = this.autoCompleteTrigger.panelClosingActions
  .subscribe((e) => {
      if (!e || !e.source) {
        const selected = this.matAutocomplete.options
          .map(option => option.value)
          .find(option => option === this.formControl.value);

        if (selected == null) {
          this.formControl.setValue(null);
        }
      }
    },
    err => this.subscribeToClosingActions(),
    () => this.subscribeToClosingActions());
}

他們在網站上給出的示例使用反應式表單方法,但在您的情況下,您似乎傾向於模板驅動方法,但您沒有使用表單周期。

因此,您可以像現在一樣直接訪問 dom 元素。

創建對輸入的本地引用,可以將其稱為 autoComplInput

在組件文件中,您需要導入ElementRef和 View Child

import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';

在您的組件中,導入 ViewChild,並將其聲明為 ElementRef 類型

@ViewChild('autoComplInput') autoComplInput: ElementRef;

然后在初始化的某個點,只需分配引用的元素值

  ngOnInit() {
    this.autoComplInput.nativeElement.value = this.countries[0];
  }

演示基於 Angular Material 2 的示例,因為您沒有提供所需的所有信息。

在你的 html

<mat-form-field>
  <input matInput
         placeholder="{{'country'}}"
         required
         [matAutocomplete]="tdAuto"
         name="country"
         #autoComplInput
         (ngModelChange)="searchCountry($event)">
  <mat-autocomplete #tdAuto="matAutocomplete" >
    <mat-option *ngFor="let country of countries" [value]="country">
      <div class="row">
        <span>{{country}} </span>
      </div>
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

在您的組件中

import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';

@Component({
  selector: '<...>',
  templateUrl: '<...>',
  styleUrls: ['<...>'],
})
export class <...> implements OnInit  {

  @ViewChild('autoComplInput') autoComplInput: ElementRef;

  countries = [
    'Alabama',
    'Alaska',
    'Arizona',
    'Arkansas',
    'California',
    'Colorado',
    'Connecticut',
    'Delaware',
    'Florida',
    'Georgia',
    'Hawaii',
    'Idaho',
    'Illinois',
    'Indiana',
    'Iowa',
    'Kansas',
    'Kentucky',
    'Louisiana',
    'Maine',
    'Maryland',
    'Massachusetts',
    'Michigan',
    'Minnesota',
    'Mississippi',
    'Missouri',
    'Montana',
    'Nebraska',
    'Nevada',
    'New Hampshire',
    'New Jersey',
    'New Mexico',
    'New York',
    'North Carolina',
    'North Dakota',
    'Ohio',
    'Oklahoma',
    'Oregon',
    'Pennsylvania',
    'Rhode Island',
    'South Carolina',
    'South Dakota',
    'Tennessee',
    'Texas',
    'Utah',
    'Vermont',
    'Virginia',
    'Washington',
    'West Virginia',
    'Wisconsin',
    'Wyoming',
  ];
  constructor( ) {}

  ngOnInit() {
    this.autoComplInput.nativeElement.value = this.countries[0];
  }


}

也許我遲到了,但我找到了這個https://onthecode.co.uk/force-selection-angular-material-autocomplete/基於驗證器的非常簡單的解決方案:

export function RequireMatch(control: AbstractControl) {
    const selection: any = control.value;
    if (typeof selection === 'string') {
        return { incorrect: true };
    }
    return null;
}

您可以創建自定義 Validator ,這將驗證它經過完美測試的代碼:

stateCtrl = new FormControl(null,[forbiddenNamesValidator(this.states)])


export function forbiddenNamesValidator(States: any[]): ValidatorFn {
  return (control: AbstractControl): { [key: string]: any } | null => {
    const index = States.findIndex(State=> {
      return (new RegExp('\^' + State.name + '\$')).test(control.value);
    });
    return index < 0 ? { 'forbiddenNames': { value: control.value } } : null;
  };
}

您也可以嘗試以下方法:

角材料自動完成組件力選擇:完整示例

這是Stackblitz上的演示

暫無
暫無

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

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