首页 > 解决方案 > 具有嵌套 JSON 结构的 Angular MatOptGroup 自动完成

问题描述

有一些使用 JSON 结构的 MatOptGroup 过滤示例,但它们不是嵌套的。这就是为什么我要解决这个问题。

 <mat-form-field>
     <mat-label>Database</mat-label>
     <mat-select [formControl]="databaseControl">
         <mat-option>-- None --</mat-option>
         <mat-optgroup *ngFor="let group of databaseGroups" [label]="group.name" [disabled]="group.disabled">
             <mat-option *ngFor="let children of group.children" [value]="children.name">
                 {{children.name}}
             </mat-option>
         </mat-optgroup>
     </mat-select>
 </mat-form-field>

目前它是这样工作的。结构嵌套如下:

 export interface Database {
   name: string;
 }

 export interface DatabaseGroup {
   disabled?: boolean;
   name: string;
   children: Database[];
 }

有一个没有嵌套结构的例子:https ://stackblitz.com/edit/angular-smg2xm?file=app/app.component.ts

我尝试过这样的事情,但这不起作用,因为过滤器不知道彼此的价值:

   private _filterGroups(value: string): string[] {
     const filterValue = value.toLowerCase();

     this.options = this.databaseGroups.filter(function (database) {
       database.children.filter(function (sipp) {
         return sipp.name.toLowerCase().includes(filterValue);
       })
     });

     return this.options;
   }

没有嵌套结构的解决方案:

filterGroup(val: string): SpeciesGroup[] {
 if (val) {
   return this.speciesGroup
     .map(group => ({ letter: group.letter, name: this._filter(group.name, val) }))
     .filter(group => group.name.length > 0);
 }

 return this.speciesGroup;
}

标签: angularautocomplete

解决方案


我解决了。

 export const _filterChildren = (opt: Database[], value: string): Database[] => {
   const filterValue = value.toLowerCase();

   return opt.filter(item => item.name.toLowerCase().indexOf(filterValue) === 0);
 };

   filteredOptions: Observable<DatabaseGroup[]>;
   databaseControl = new FormControl();
   databaseGroups: DatabaseGroup[];

   private _filterGroup(value: string): DatabaseGroup[] {
     if (value) {
       return this.databaseGroups
         .map(group => ({ children: _filterChildren(group.children, value), name: group.name }))
         .filter(group => group.children.length > 0);
     }

     return this.databaseGroups;
   }

   ngOnInit() {
     this.filteredOptions = this.databaseControl.valueChanges
       .pipe(
         startWith(''),
         map(value => this._filterGroup(value))
       );
   }
 <mat-form-field>
     <mat-label>{{'CSV.DBATTR' | translate}}</mat-label>
     <input matInput placeholder="{{'CSV.CHOOSE' | translate}}" [matAutocomplete]="auto"
         [formControl]="databaseControl">
     <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
         <mat-option>{{'CSV.NONE' | translate}}</mat-option>
         <mat-optgroup *ngFor="let group of filteredOptions | async" [label]="group.name">
             <mat-option *ngFor="let children of group.children" [value]="children.name">
                 {{children.name}}
             </mat-option>
         </mat-optgroup>
     </mat-autocomplete>
 </mat-form-field>

您可以在问题中找到两个使用过的界面,您现在可以自动完成子项,但只能自动完成子项。如果有人知道如何自动完成父母或选择组,请随时回答。


推荐阅读