Angular Material Autocomplete force selection

后端 未结 6 1458
情书的邮戳
情书的邮戳 2021-02-07 09:18

In my angular 5 application I have some matAutocomplete, but I want to force the selection of oone of suggestions, so I am following this approach: stackblitz but for some reas

相关标签:
6条回答
  • 2021-02-07 10:15

    You can also try the following method:

    Angular Material Autocomplete Component Force Selection: Complete Example

    Here is the demo on Stackblitz

    0 讨论(0)
  • 2021-02-07 10:16

    The example they give on the site uses Reactive Form approach, but in your case you seem to lean toward Template Driven Approach, but you're not using a form period.

    So you could directly access the dom element like you're doing now.

    Create a local reference to your input, maybe call it autoComplInput

    Inside your component file, you'll want to import ElementRef and View Child

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

    Inside your component, import ViewChild, and declare it an ElementRef type

    @ViewChild('autoComplInput') autoComplInput: ElementRef;
    

    Then at some point of initialization, just assign referenced element value

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

    Demo based on Angular Material 2's example, since you didn't provide all the information needed.

    In your 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>
    

    In your component

    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];
      }
    
    
    }
    
    0 讨论(0)
  • 2021-02-07 10:18

    Using blur event and matAutocomplete output event (optionSelected) we can force user to select option.

    <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 file functions

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

    depend on your requirement you can always delay the function which you call in blur or optionSelect event using setTimeout window function.

    setTimeout(()=> { 
    // function contents
    }, 1000);
    
    0 讨论(0)
  • 2021-02-07 10:18

    You can Create custom Validator , this will validate it perfectly tested code:

    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;
      };
    }
    
    0 讨论(0)
  • 2021-02-07 10:21

    I found this helpful:

    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());
    }
    
    0 讨论(0)
  • 2021-02-07 10:22

    maybe I'm late, but I fount this https://onthecode.co.uk/force-selection-angular-material-autocomplete/ Really simple solution based on validator:

    export function RequireMatch(control: AbstractControl) {
        const selection: any = control.value;
        if (typeof selection === 'string') {
            return { incorrect: true };
        }
        return null;
    }
    
    0 讨论(0)
提交回复
热议问题