【问题标题】:How to use angular material 6 autocomplete with data server如何在数据服务器中使用 Angular Material 6 自动完成功能
【发布时间】:2018-11-12 01:49:39
【问题描述】:

我正在使用 Angular 6 和 Material 6 开发一个简单的页面。我想使用 Material 的自动完成功能从服务中恢复数据,但我不知道如何做好。

来自官方示例https://material.angular.io/components/autocomplete/overview我不明白如何使用服务将其与自动完成集成。

谁能帮帮我?

谢谢

【问题讨论】:

  • 您有任何已经返回过滤数据的服务吗?
  • 是的!我正在构建一个 POC,并且我正在使用一个暂时返回虚假数据的服务。未来,该服务将是一个真正的服务,具有本部分声明的定义。
  • 感谢@Yousef 的快速回复!

标签: angular autocomplete angular-material


【解决方案1】:

让我们假设你从服务器返回你的数据作为具有 IyourAwesomeData 结构的对象,为了这个示例的目的,我们将使用字段 someName 来过滤数据

所以你的 ts 组件应该是这样的:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormControl } from '@angular/forms';
import { startWith, debounceTime, map, switchMap, distinctUntilChanged } from 'rxjs/operators';
import { Subscription } from 'rxjs';

interface IyourAwesomeData {
 someName: string; 
 someField: string;
 someOtherField: number;
}

export class YourAutcompleteComponent implements OnInit, OnDestroy {

  dataFiltered: IyourAwesomeData[]; // this data will be used inside HTML Template
  data: Observable<IyourAwesomeData[]>; 
  yourInputCtrl = new FormControl();
  private sub: Subscription;

  constructor() {}

  ngOnInit() {
    this.data = ??? // Pass your data as Observable<IyourAwesomeData[]>;
    this.sub = this.yourInputCtrl.valueChanges
      .pipe(
        debounceTime(500),
        distinctUntilChanged(), 
        startWith(''),
        switchMap((val) => {
          return this.filterData(val || '');
        })
      ).subscribe((filtered) => {
        this.dataFiltered = filtered;
      });
  }

  ngOnDestroy() {
     this.sub.unsubscribe();
  }

  filterData(value: string) {
    return this.data // like IyourAwesomeData[]
      .pipe(
        map((response) => response.filter((singleData: IyourAwesomeData) => {
          return singleData.someName.toLowerCase().includes(value.toLowerCase())
        })),
    );
  }
}

你的 HTML 模板应该是这样的:

<mat-form-field>
  <input matInput placeholder="some placeholder" [matAutocomplete]="auto" [formControl]="yourInputCtrl">
  <mat-autocomplete #auto="matAutocomplete">
    <mat-option *ngFor="let single of dataFiltered" [value]="single.someName">
      {{ single.someName }}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

【讨论】:

  • 我会尝试这个解决方案,稍后我会告诉你结果;)
  • 你在哪里订阅了 api 结果?
  • 在 ngOnInit() 内部,但我不订阅此数据,只是分配给 this.data Observable,例如,我使用的是 firebase,在我的服务中,我正在获取类似 getData() 的数据:Observable { return this.someColection.valueChanges(); } 和里面 ngoninit this.data = this.myService.getData();
【解决方案2】:

终于,我找到了我想做的事情的解决方案! 要将 FormArray 绑定到 mat-table 数据源,您必须: 简单来说,例子是这样的:

<table mat-table [dataSource]="itemsDataSource">
  <ng-container matColumnDef="itemName">
    <td mat-cell *matCellDef="let element">{{ element.value.material?.name }}</td>
  </ng-container>
  <ng-container matColumnDef="itemCount">
    <td mat-cell *matCellDef="let element">{{ element.value.itemCount }}</td>
  </ng-container>
  <tr mat-row *matRowDef="let row; columns: itemColumns;"></tr>
</table>

和代码:

export class ItemListComponent implements OnInit {
  constructor(
    private fb: FormBuilder
  ) { }
  itemColumns = ['itemName', 'count'];
  itemForm: FormGroup;
  itemsDataSource = new MatTableDataSource();
  get itemsForm() {
    return this.itemForm.get('items') as FormArray;
  }
  newItem() {
    const a = this.fb.group({
      material: new FormControl(), //{ name:string }
      itemCount: new FormControl() // number 
    });
    this.itemsForm.push(a);
    this.itemsDataSource._updateChangeSubscription(); //neccessary to render the mat-table with the new row
  }
  ngOnInit() {
    this.itemForm = this.fb.group({
      items: this.fb.array([])
    });
    this.newItem();
    this.itemsDataSource.data = this.itemsForm.controls;
  }
}

【讨论】:

【解决方案3】:

您只需在用户更改输入值后立即从服务器数据中填充options

<input type="text" matInput (input)="onInputChanged($event.target.value)" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
  <mat-option *ngFor="let option of options" [value]="option">{{ option.title }}</mat-option>
</mat-autocomplete>

在你的组件文件中,你需要处理onInputChanged(searchStr)options

onInputChanged(searchStr: string): void {
    this.options = [];
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
    this.subscription = this.yourService.getFilteredData(searchStr).subscribe((result) => {
        this.options = result;
      });
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-22
    • 2018-11-27
    • 1970-01-01
    • 2018-12-19
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多