我如何在 <mat-select> 中实现自动完成?成分? [英] How do I implement autocomplete in a <mat-select> component?

查看:22
本文介绍了我如何在 <mat-select> 中实现自动完成?成分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将自动完成功能与多选垫选择器结合起来,因为选项列表会很长.

我已经在 stackoverflow 上搜索了答案,最接近答案的是这个 为<mat-select>实现一个搜索过滤器.角材料的组成部分

然而,这些示例是关于 table 而不是 mat-select.

我的问题是,是否可以将自动完成功能添加到 mat-select.如果不能,我是否可以在列表中的每个项目前设置一个包含复选框的自动完成功能?

谢谢

我发现 angular 的 primefaces 确实有一个多选列表,允许您搜索列表项.它还包括一个内置的全选按钮!你可以在这里找到它https://www.primefaces.org/primeng/#/multiselect

您可以使用 npm install primeng --save

安装 primefaces

解决方案

您可以使用 MatAutocomplete 和一些技巧来实现自动完成多选.我很确定你不能用 MatSelect 来做到这一点,因为它不能让你控制输入元素.该技术有点奇怪,但效果很好.这个想法是在你的控制器中管理选择,并将每个 mat-option 的值"设置为相同的东西 - 你选择的选项.您还需要捕获点击以允许用户与列表交互(而不是在点击时立即关闭),当然还需要在 mat-option 项目内提供复选框.还需要一些其他技巧 - 这是一个快速而肮脏的示例,显示了该怎么做.

HTML:

<input type="text" placeholder="选择用户" aria-label="选择用户" matInput [matAutocomplete]="auto" [formControl]="userControl"><mat-h​​int>输入文本以按名称查找用户</mat-h​​int></mat-form-field><mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn"><mat-option *ngFor="让filteredUsers 的用户| async" [value]="selectedUsers"><div (click)="optionClicked($event, user)"><mat-checkbox [checked]="user.selected" (change)="toggleSelection(user)" (click)="$event.stopPropagation()">{{ user.firstname }} {{ user.lastname }}</mat-checkbox>

</mat-option></mat-autocomplete><br><br><label>选定的用户:</label><mat-list密集><mat-list-item *ngIf="selectedUsers?.length === 0">(无)</mat-list-item><mat-list-item *ngFor="让 selectedUsers 的用户">{{ user.firstname }} {{ user.lastname }}</mat-list-item></mat-list>

TS:

import { Component, OnInit, ViewChild } from '@angular/core';从@angular/forms"导入{FormControl};从 'rxjs' 导入 { Observable };import { map, startWith } from 'rxjs/operators';导出类用户{构造函数(公共名字:字符串,公共姓氏:字符串,公共选择?:布尔){if (selected === undefined) selected = false;}}/*** @title 多选自动完成*/@成分({选择器:多选自动完成示例",templateUrl: 'multiselect-autocomplete-example.html',styleUrls: ['multiselect-autocomplete-example.css']})导出类 MultiselectAutocompleteExample 实现 OnInit {userControl = new FormControl();用户 = [新用户('米莎','阿诺德'),新用户('Felix', 'Godines'),新用户('敖德萨','索顿'),新用户('朱丽安','吉尔斯'),新用户('维吉尔','霍梅尔'),新用户('贾斯塔','贝茨'),新用户('Keely', 'Millington'),新用户('布兰卡','温泽'),新用户('亚历杭德里娜','帕拉斯'),新用户('玫瑰色','小费'),新用户('薇诺娜','凯里克'),新用户('雷纳尔多','果园'),新用户('肖恩','Counce'),新用户('Shemeka','Wittner'),新用户('Sheila', 'Sak'),新用户('左拉','罗达斯'),新用户('德娜','海尔曼'),新用户('康塞普西翁','皮克雷尔'),新用户('玛丽莲','伯蒂奥姆'),新用户('霍华德','立顿'),新用户('马克辛','阿蒙'),新用户('伊莲娜','Steck'),新用户('拉维纳','塞斯纳'),新用户('布列塔尼','罗施'),新用户('Esteban','Ohlinger'),新用户('迈伦','科特纳'),新用户('杰里','唐纳'),新用户('明娜','瑞克曼'),新用户('Yi', 'Grieco'),新用户('劳埃德','斯尼德'),新用户('侯爵','威尔蒙'),新用户('露皮塔','马特恩'),新用户('费尔南德','推卸'),新用户('埃洛伊斯','麦卡弗里'),新用户('艾布拉姆','帽子'),新用户('卡丽莎','米莱拉'),新用户('贝利','伊诺'),新用户('朱莉安','辛克莱'),新用户('吉赛尔','拉布达'),新用户('切尔西','Hy'),新用户('卡蒂娜','Wohlers'),新用户('埃德里斯','自由人'),新用户('哈利','多塞特'),新用户('Yasmin', 'Bohl'),新用户('夏安','奥斯特伦德'),新用户('乔安妮','格林利'),新用户('Sherril', 'Colin'),新用户('玛丽安','弗拉斯卡'),新用户('塞纳','亨宁森'),新用户('Cami','Ringo')];selectedUsers: User[] = new Array();过滤用户:可观察的<用户[]>;lastFilter: 字符串 = '';ngOnInit() {this.filteredUsers = this.userControl.valueChanges.pipe(startWith(''),map(value => typeof value === 'string' ? value : this.lastFilter),地图(过滤器 => this.filter(过滤器)));}过滤器(过滤器:字符串):用户[] {this.lastFilter = 过滤器;如果(过滤器){返回 this.users.filter(option => {返回 option.firstname.toLowerCase().indexOf(filter.toLowerCase()) >= 0||option.lastname.toLowerCase().indexOf(filter.toLowerCase()) >= 0;})} 别的 {返回 this.users.slice();}}displayFn(value: User[] | string): string |不明确的 {让显示值:字符串;如果 (Array.isArray(value)) {value.forEach((user, index) => {如果(索引=== 0){displayValue = user.firstname + ' ' + user.lastname;} 别的 {displayValue += ', ' + user.firstname + ' ' + user.lastname;}});} 别的 {显示值 = 值;}返回显示值;}optionClicked(事件:事件,用户:用户){event.stopPropagation();this.toggleSelection(user);}切换选择(用户:用户){user.selected = !user.selected;如果(用户选择){this.selectedUsers.push(user);} 别的 {const i = this.selectedUsers.findIndex(value => value.firstname === user.firstname && value.lastname === user.lastname);this.selectedUsers.splice(i, 1);}this.userControl.setValue(this.selectedUsers);}}

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 stackoverflow for the answer and the closest to an answer was this implement a search filter for the <mat-select> component of angular material

However the examples are about table and not mat-select.

My question is, is it possible to add the autocomplete feature to mat-select. And if not could i make an autocomplete that includes checkboxes in front of each item in the list?

Thank you

EDIT: I've found out that primefaces for angular does have a multiselect list that allows you to search for listitems. It also includes a builtin select-all button! You can find it here https://www.primefaces.org/primeng/#/multiselect

You can install primefaces with npm install primeng --save

解决方案

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:

<mat-form-field class="example-full-width">
    <input type="text" placeholder="Select Users" aria-label="Select Users" matInput [matAutocomplete]="auto" [formControl]="userControl">
    <mat-hint>Enter text to find users by name</mat-hint>
</mat-form-field>

<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
    <mat-option *ngFor="let user of filteredUsers | async" [value]="selectedUsers">
        <div (click)="optionClicked($event, user)">
            <mat-checkbox [checked]="user.selected" (change)="toggleSelection(user)" (click)="$event.stopPropagation()">
                {{ user.firstname }} {{ user.lastname }}
            </mat-checkbox>
        </div>
    </mat-option>
</mat-autocomplete>

<br><br>

<label>Selected Users:</label>
<mat-list dense>
    <mat-list-item *ngIf="selectedUsers?.length === 0">(None)</mat-list-item>
    <mat-list-item *ngFor="let user of selectedUsers">
        {{ user.firstname }} {{ user.lastname }}
    </mat-list-item>
</mat-list>

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

  filteredUsers: Observable<User[]>;
  lastFilter: string = '';

  ngOnInit() {
    this.filteredUsers = this.userControl.valueChanges.pipe(
      startWith<string | User[]>(''),
      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);
  }

}

这篇关于我如何在 &lt;mat-select&gt; 中实现自动完成?成分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆