How do i implement autocomplete in a component?

后端 未结 3 1577
甜味超标
甜味超标 2020-12-16 00:37

I would like to combine the autocomplete feature with a multiselect mat-select chooser because the optionslist will be quite long.

I\'ve already searched on stackove

3条回答
  •  北荒
    北荒 (楼主)
    2020-12-16 01:03

    You can implement an autocomplete multi-select using MatAutocomplete and some tricks. I'm fairly sure you can't do it with MatSelect since that doesn't give you control over the input element. The technique is a little odd, but it works fine. The idea is to manage selections in your controller, and set the "value" of each mat-option to the same thing - your selected options. You also need to trap clicks to allow users to interact with the list (rather than have it close immediately when clicked), and of course provide checkboxes inside the mat-option items. A few other tricks are necessary as well - here is a quick and dirty example that shows what to do.

    HTML:

    
        
        Enter text to find users by name
    
    
    
        
            
    {{ user.firstname }} {{ user.lastname }}


    (None) {{ user.firstname }} {{ user.lastname }}

    TS:

    import { Component, OnInit, ViewChild } from '@angular/core';
    import { FormControl } from '@angular/forms';
    import { Observable } from 'rxjs';
    import { map, startWith } from 'rxjs/operators';
    
    export class User {
      constructor(public firstname: string, public lastname: string, public selected?: boolean) {
        if (selected === undefined) selected = false;
      }
    }
    
    /**
     * @title Multi-select autocomplete
     */
    @Component({
      selector: 'multiselect-autocomplete-example',
      templateUrl: 'multiselect-autocomplete-example.html',
      styleUrls: ['multiselect-autocomplete-example.css']
    })
    export class MultiselectAutocompleteExample implements OnInit {
    
      userControl = new FormControl();
    
      users = [
        new User('Misha', 'Arnold'),
        new User('Felix', 'Godines'),
        new User('Odessa', 'Thorton'),
        new User('Julianne', 'Gills'),
        new User('Virgil', 'Hommel'),
        new User('Justa', 'Betts'),
        new User('Keely', 'Millington'),
        new User('Blanca', 'Winzer'),
        new User('Alejandrina', 'Pallas'),
        new User('Rosy', 'Tippins'),
        new User('Winona', 'Kerrick'),
        new User('Reynaldo', 'Orchard'),
        new User('Shawn', 'Counce'),
        new User('Shemeka', 'Wittner'),
        new User('Sheila', 'Sak'),
        new User('Zola', 'Rodas'),
        new User('Dena', 'Heilman'),
        new User('Concepcion', 'Pickrell'),
        new User('Marylynn', 'Berthiaume'),
        new User('Howard', 'Lipton'),
        new User('Maxine', 'Amon'),
        new User('Iliana', 'Steck'),
        new User('Laverna', 'Cessna'),
        new User('Brittany', 'Rosch'),
        new User('Esteban', 'Ohlinger'),
        new User('Myron', 'Cotner'),
        new User('Geri', 'Donner'),
        new User('Minna', 'Ryckman'),
        new User('Yi', 'Grieco'),
        new User('Lloyd', 'Sneed'),
        new User('Marquis', 'Willmon'),
        new User('Lupita', 'Mattern'),
        new User('Fernande', 'Shirk'),
        new User('Eloise', 'Mccaffrey'),
        new User('Abram', 'Hatter'),
        new User('Karisa', 'Milera'),
        new User('Bailey', 'Eno'),
        new User('Juliane', 'Sinclair'),
        new User('Giselle', 'Labuda'),
        new User('Chelsie', 'Hy'),
        new User('Catina', 'Wohlers'),
        new User('Edris', 'Liberto'),
        new User('Harry', 'Dossett'),
        new User('Yasmin', 'Bohl'),
        new User('Cheyenne', 'Ostlund'),
        new User('Joannie', 'Greenley'),
        new User('Sherril', 'Colin'),
        new User('Mariann', 'Frasca'),
        new User('Sena', 'Henningsen'),
        new User('Cami', 'Ringo')
      ];
    
      selectedUsers: User[] = new Array();
    
      filteredUsers: Observable;
      lastFilter: string = '';
    
      ngOnInit() {
        this.filteredUsers = this.userControl.valueChanges.pipe(
          startWith(''),
          map(value => typeof value === 'string' ? value : this.lastFilter),
          map(filter => this.filter(filter))
        );
      }
    
      filter(filter: string): User[] {
        this.lastFilter = filter;
        if (filter) {
          return this.users.filter(option => {
            return option.firstname.toLowerCase().indexOf(filter.toLowerCase()) >= 0
              || option.lastname.toLowerCase().indexOf(filter.toLowerCase()) >= 0;
          })
        } else {
          return this.users.slice();
        }
      }
    
      displayFn(value: User[] | string): string | undefined {
        let displayValue: string;
        if (Array.isArray(value)) {
          value.forEach((user, index) => {
            if (index === 0) {
              displayValue = user.firstname + ' ' + user.lastname;
            } else {
              displayValue += ', ' + user.firstname + ' ' + user.lastname;
            }
          });
        } else {
          displayValue = value;
        }
        return displayValue;
      }
    
      optionClicked(event: Event, user: User) {
        event.stopPropagation();
        this.toggleSelection(user);
      }
    
      toggleSelection(user: User) {
        user.selected = !user.selected;
        if (user.selected) {
          this.selectedUsers.push(user);
        } else {
          const i = this.selectedUsers.findIndex(value => value.firstname === user.firstname && value.lastname === user.lastname);
          this.selectedUsers.splice(i, 1);
        }
    
        this.userControl.setValue(this.selectedUsers);
      }
    
    }
    

提交回复
热议问题