MatAutocomplete高级属性特殊用法

概述

在表单的设计过程中,会有一些表单字段需要在已知的内容中进行选择,这在html中会使用select组件来设计该表单字段。而在Material中,同样有与之对应的 <mat-select> 组件。这种组件在选项内容较少的情况下使用非常方便,
能很好的引导用户在表单中,输入规范的内容:

图片

但是在选项内容过多时,这种 <mat-select> 组件,对用户来说,想要找到自己想要的选项就比较麻烦,需要一个个选项去对比,查找:

图片


幸运的是,在Material中提供了 mat-autocomplete ,这个组件和我们以前在JQuery时代使用的select2类似。它支持用户键盘输入功能,并根据输入内容在已有的数据集合中进行过滤,选项内容动态的显示过滤后的结果。




MatAutocomplete


基本用法

html:

<form class="example-form">
 <mat-form-field class="example-full-width">
   <input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto">
   <mat-autocomplete #auto="matAutocomplete">
     <mat-option *ngFor="let option of options" [value]="option">
       {{option}}      </mat-option>
   </mat-autocomplete>
 </mat-form-field></form>






TypeScript:

import {Component} from '@angular/core';import {FormControl} from '@angular/forms';/**
* @title Simple autocomplete
*/

@Component({
 selector: 'autocomplete-simple-example',
 templateUrl: 'autocomplete-simple-example.html',
 styleUrls: ['autocomplete-simple-example.css'],
})export class AutocompleteSimpleExample {
 myControl = new FormControl();
 options: string[] = ['One', 'Two', 'Three'];
}






呈现的效果如下:

图片


高级API

在简单用法中,我们发现,选项内容为字符串,选择中的值和显示的值为相同的。但在实际的应用过程中,我们需要选中的值和显示的内容是不同的。

displayWith

举个例子,我们有个需要选择企业的字段,要存储到数据库的值是企业的编码,而在界面上显示的需要是企业的名称。
在这个例子中,我们有个企业的数据结构:

interface Company {
 code: string;
 name: string;
}


companies: Company[] = []; constructor() {    this.companies.push({code: 'qiye-01', name: '企业01'});    this.companies.push({code: 'qiye-02', name: '企业02'});    this.companies.push({code: 'qiye-03', name: '企业03'});    this.companies.push({code: 'qiye-04', name: '企业04'});
}
<form class="example-form">
 <mat-form-field class="example-full-width">
   <input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto">
   <mat-autocomplete #auto="matAutocomplete">
     <mat-option *ngFor="let option of companies" [value]="option">
       {{option.name}}      </mat-option>
   </mat-autocomplete>
 </mat-form-field></form>






在html中,我们将mat-option的显示内容修改成name,如 {{option.name}} 。这样我们的下拉选项中就会显示企业的名称:

但是如果我们选中其中一个选项,就会发现结果和我们想象的不一样,选中后的结果显示并不是我们想要的企业名称
图片


此时,我们就需要使用API中提供的

在MatAutocomplete的API: displayWith。文档已经很明确的告诉我们 displayWith 需要我们传入一个已定义的函数

@Input()
displayWith: ((value: any) => string) | null

其中的函数形参value指的是 <mat-option *ngFor="let option of companies" [value]="option"> 中value对应的option,此处option就是一个我们后台定义的Company。这样我们的value就拥有code和name两个属性。

这样我们就可以定义一个displayWith的函数:

displayFn(value: any): string { // value: Company
 return value ? value.name : undefined;
}

同时修改html

<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
 <mat-option *ngFor="let option of companies" [value]="option">
   {{option.name}}  </mat-option></mat-autocomplete>

这样就会显示我们想要的结果
图片

在这种方式下,我们的formControl得到的其实是一个company对象,要存储code,需要在从company对象中获取code属性值。

那么如果我们想在formControl中直接得到code呢?

扩展用法
通过分析,我们发现,formControl获得值的内容,其实和中的value是一致的。

因此,我们可以做如下修改, 将value改成option.code

<form class="example-form">
 <mat-form-field class="example-full-width">
   <input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto">
   <mat-autocomplete #auto="matAutocomplete">
     <mat-option *ngFor="let option of companies" [value]="option.code">
       {{option.name}}      </mat-option>
   </mat-autocomplete>
 </mat-form-field></form>






得到如下显示结果:
图片

发现显示的是code值,那我们还可以使用displayWith函数,让它显示企业名称吗?

答案是可以的。不过我们就不能在使用上面定义的displayFn方法了。
此时我们需要重新定义一个更高级的方法:

displayWith() {  return (value) => {    if (value) {      const arr = that.companies.filter(item => item.code === value);      if (arr.length) {        return arr[0].name;
     }
   }    return undefined;
 }
}



在html中的使用方法如下:

<form class="example-form">
 <mat-form-field class="example-full-width">
   <input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto">
   <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayWith()">
     <mat-option *ngFor="let option of companies" [value]="option.code">
       {{option.name}}      </mat-option>
   </mat-autocomplete>
 </mat-form-field></form>






需要[displayWith]=”displayWithThis(this)” 这样特殊的使用方法。

为什么同样是用displayWith,不同的value中,实际写法差异却如此大呢?
这个和JS的This作用于有关。

在不是用匿名函数的情况下,如:

displayFn(value) {    if (value) {        const arr = this.companies.filter(item => item.code === value);        if (arr.length) {            return arr[0].name;
       }
   }    return undefined;
}


此时,如果将displayFn直接设置到mat-autocomplete中,此时的this表示mat-autocomplete对象,这样this.companies.filter就会抛出异常。


结论

在本文中,我们主要讲了MatAutocomplete在实际开发过程中,在不同的业务场景中,同样的组件我们用到的不同的实现方式。每一种语言都有它自己的特性,掌握了这些特性,会让我们工作时更加得心应手。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章