角度材料自动完成力选择

时间:2018-01-24 09:34:26

标签: angular angular-material

在我的angular 5应用程序中,我有一些matAutocomplete,但我想强制选择一些建议,所以我遵循这种方法: stackblitz 但出于某种原因,我有一个问题:

  

无法读取未定义的属性'panelClosingActions'       在CustomerDetailComponent.countryClosingActions(customer-detail.component.ts:199)       在CustomerDetailComponent.ngAfterViewInit

我有多个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());
  }

6 个答案:

答案 0 :(得分:5)

使用模糊事件和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() {
    if (!this.selectedCountry || this.selectedCountry !== this.signatureFormGroup.controls['country'].value) {
      this.signatureFormGroup.controls['country'].setValue(null);
      this.selectedCountry = '';
    }
  }

答案 1 :(得分:1)

我发现this有帮助:

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());
}

答案 2 :(得分:0)

他们在网站上提供的示例使用Reactive Form方法,但在您的情况下,您似乎倾向于模板驱动方法,但您没有使用表单期间。

所以你可以像现在一样直接访问dom元素。

创建对输入的本地引用,也可以将其命名为autoComplInput  

在您的组件文件中,您需要导入ElementRef并查看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];
  }


}

答案 3 :(得分:0)

您可以创建自定义的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;
  };
}

答案 4 :(得分: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;
}

答案 5 :(得分:0)