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在实际开发过程中,在不同的业务场景中,同样的组件我们用到的不同的实现方式。每一种语言都有它自己的特性,掌握了这些特性,会让我们工作时更加得心应手。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值