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在實際開發過程中,在不同的業務場景中,同樣的組件我們用到的不同的實現方式。每一種語言都有它自己的特性,掌握了這些特性,會讓我們工作時更加得心應手。


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