網站搜尋

TypeScript - 在 Angular 的對話框視窗中使用 mat chip 列表?


然後當使用者輸入一些資料時,應該以預先填充的 mat-chips 列表格式顯示從資料庫取得的相關甜點列表數據如下:(如果這不可能,我們可以顯示一個從資料庫預先填充的可用甜點下拉選單,讓使用者從中選擇),但已經選擇的值(重複)不應該出現在下拉選單中,也不應該透過輸入再次提示使用者選擇,無論對話框仍然開啟或已關閉再重新打開。因為所選甜點應該是唯一的,因為這個 chip 資料將被存儲在資料庫的另一個表中。

使用者可以從顯示的可用項目列表中刪除或添加任何他想要的芯片,然後點擊提交。但這裡的條件應該是,一旦一個芯片項目被選中(不關閉該項目即視為已選擇提交),就不能再次通過輸入或者之前的提交來選擇重複的芯片項目。這意味著:例如,如果我有5個預先填充的芯片項目,如圖所示,使用者不能輸入新的芯片項目並提交;另外,如果芯片4和芯片5已被選中,而芯片1、芯片2、芯片3已從顯示列表中關閉(刪除),那麼提交時只能將不重複的1個芯片4和1個芯片5傳送到通過按鈕點擊事件調用此對話框的頁面上。再者,當使用者再次打開此對話框時,之前選擇的芯片4和5不應再次出現在模態芯片列表中。

我已經嘗試按照 Angular Material 文檔中所述完全實現自動完成類型的 mat chip 列表,如下所示,但那會打開一個下拉菜單,而不是所需的格式。

desserts.component.html:

    <div mat-dialog-content>
  <form>
    <div>
        <mat-form-field appearance="outline">
            <mat-label>Dessert*</mat-label>
            <mat-chip-list multiple #chipList>
              <mat-chip
                *ngFor="let dessert of desserts"
                [selectable]="selectable"
                [removable]="removable"
                (removed)="remove(dessert)">
                {{dessert}}
                <mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
              </mat-chip>
              <input
                placeholder="Dessert Name"
                #dessertInput
                [formControl]="dessertListCtrl"
                [matAutocomplete]="auto"
                [matChipInputFor]="chipList"
                [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
                [matChipInputAddOnBlur]="addOnBlur"
                (matChipInputTokenEnd)="add($event)">
            </mat-chip-list>
            <mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
              <mat-option *ngFor="let dessert of filteredDesserts | async" [value]="dessert">
                {{dessert}}
              </mat-option>
            </mat-autocomplete>
        </mat-form-field>
        <button mat-button (click)="onSubmit()">Submit</button>
      </div>
      </form>
</div>

desserts.component.ts:

export class DessertsComponent{
    
    selectable = true;
    removable = true;
    addOnBlur = true;
    separatorKeysCodes: number[] = [ENTER, COMMA];
    dessertListCtrl = new FormControl();
    filteredDesserts: Observable<string[]>;
    desserts: string[] = [];
    dessertsList: any = [];
    
    @ViewChild('dessertInput',{static: false}) dessertInput: ElementRef<HTMLInputElement>;
    @ViewChild('auto',{static: false}) matAutocomplete: MatAutocomplete;
  
    constructor(
                  private dbService: DBService,
                  public dialogRef: MatDialogRef<DessertsComponent>,
                  @Inject(MAT_DIALOG_DATA) public data: any,
               ) {
                    
                    this.dessertsListData();
                    this.filteredDesserts = this.dessertListCtrl.valueChanges.pipe(
                        startWith(null),
                        map((dessert: string | null) => dessert ? this._filter(dessert) : this.dessertsList.slice()));
                 }  
    dessertsListData(){
      this.dbService.dessertsListData().subscribe(
        (response: any) => {
          this.dessertsList = response;
        });
    }
    add(event: MatChipInputEvent): void {
      if (!this.matAutocomplete.isOpen) {
        const input = event.input;
        const value = event.value;
        
        if ((value || '').trim()) {
            this.desserts.push(value.trim());
        }
        
        if (input) {
          input.value = '';
        }
  
        this.dessertListCtrl.setValue(null);
      }
    }
  
    remove(dessert: string): void {
      const index = this.desserts.indexOf(dessert);
  
      if (index >= 0) {
        this.desserts.splice(index, 1);
      }
    }
    
    selected(event: MatAutocompleteSelectedEvent): void {
      this.desserts.push(event.option.viewValue);
      this.dessertInput.nativeElement.value = '';
      this.dessertListCtrl.setValue(null);
    }
  
    private _filter(value: string): string[] {
      const filterValue = value.toLowerCase();
      return this.dessertsList.filter(dessert => dessert.toLowerCase().indexOf(filterValue) === 0);
    }
    onSubmit(){
      this.dialogRef.close({data: this.desserts});
    }
  }

這個甜點組件正在被從另一個組件調用 this.dialog.open(DessertsComponent)

我不是 Angular Material(v7) 的專家,所以如果有人能提供這個問題的解決方案,我將非常感激和感謝。