简体   繁体   中英

How bind to an Id in an Angular Material Autocomplete drop-down, but filter by the string representation

I have an Angular Material Autocomplete drop-down with a filter that filters by CustomerName .

This was implemented via my returned Customers from my getAllCustomers() method. I then do a loop through each Customer to push the CustomerName into a new array , which essentially becomes my filteredOptions .

My question is: How can I implement this filter with the search on the CustomerName, but have a binding to the Id of each Customer?

In the object that I eventually want to save, I want to save the Customer.Id and not the CustomerName .

I have tried creating a new object array , containing both the CustomerName and Id , but this does not work with the filteredOptions and filter method. It seems like the filter method only takes an array with single values and not objects .

Also, I would need to bind this correctly in my HTML .

Here is my basic fileredOptions implementation: (Note: I included my object {name: element.CustomerName, id: element.Id} that I wish to use. This doesn't work as explained. The working method simply pushes element.CustomerName into the array :

filteredOptions: Observable<string[]>;

constructor(private loadDataService: LoadDataService, private assetDataService: AssetDataService, private router: Router, private toastr: ToastrService) { }

ngOnInit() {
    this.getAllCustomers();
}

filter(val: string): string[] {
    return this.customerNameArray.filter(option => option.toLowerCase().indexOf(val.toLowerCase()) === 0);
}

getAllCustomers() {
  this.loadDataService.getAllCustomers()
  .subscribe(data => {
    this.customerArray = data;
    let thisArray = [];
    this.customerArray.forEach(element => {
      thisArray.push({name: element.CustomerName, id: element.Id});
    });
    this.customerNameArray = thisArray;
    this.filteredOptions = this.myCustomerSearchControl.valueChanges.pipe(
      startWith(''),
      map(val => this.filter(val))
    );
  });
} 

Here is my HTML :

<mat-form-field>
    <input type="text" placeholder="Customer Search" aria-label="Number" matInput [formControl]="myCustomerSearchControl" [matAutocomplete]="auto">
        <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
            <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
            {{ option }}
        </mat-option>
    </mat-autocomplete>
</mat-form-field>

If you use an object for your options, you will need to modify your filter function and filteredOptions to use the object and not a string array. You will also need to use the displayWith feature of mat-autocomplete to allow the input to work with the object. A stackblitz example is here .

Your code:

export class Customer{
    constructor(public CustomerName: string, public Id: number) { }
}

...

filteredOptions: Observable<Customer[]>;

constructor(private loadDataService: LoadDataService, private assetDataService: AssetDataService, private router: Router, private toastr: ToastrService) { }

ngOnInit() {
    this.getAllCustomers();
}

filter(val: any) {
    let name = val.CustomerName || val; // val can be Customer or string
    return this.customerNameArray.filter(option => option.CustomerName.toLowerCase().indexOf(name.toLowerCase()) === 0);
}

getAllCustomers() {
    this.loadDataService.getAllCustomers()
    .subscribe(data => {
        this.customerArray = data;
        let thisArray = [];
        this.customerArray.forEach(element => {
            thisArray.push(new Customer(element.CustomerName, element.Id));
        });
        this.customerNameArray = thisArray;
        this.filteredOptions = this.myCustomerSearchControl.valueChanges.pipe(
            startWith(null),
            map(val => this.filter(val))
        );
    });
}

displayCustomer(cust: Customer) {
    return cust ? cust.CustomerName : '';
}

HTML:

<mat-form-field>
    <input type="text" placeholder="Customer Search" aria-label="Number" matInput [formControl]="myCustomerSearchControl" [matAutocomplete]="auto">
        <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete" [displayWith]="displayCustomer">
            <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
            {{ option.CustomerName }}
        </mat-option>
    </mat-autocomplete>
</mat-form-field>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM