Angular Material Autocomplete如何绑定JSON对象到mat-option
The issue you’re facing happens because when you bind an entire object to [value], the input field doesn’t know how to render it as a human-readable string—hence showing [object Object]. Angular Material’s mat-autocomplete has a built-in solution for this: the displayWith property, which lets you define what text to show in the input while keeping the full object as the form control’s value.
Here’s how to implement the fix step by step:
Step 1: Update the Template (HTML)
Modify your mat-autocomplete to use the full product object as the [value], and add the displayWith attribute pointing to a helper function we’ll define next:
<mat-form-field class="example-full-width"> <mat-label>Enter product name</mat-label> <input matInput aria-label="product name" [matAutocomplete]="auto" formControlName="product_name" (input)="onSearchChange($event.target.value)"> <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayProductName"> <mat-option *ngFor="let state of product_list" [value]="state"> <span>{{state.name}}</span> </mat-option> <mat-option *ngIf="!product_list || !product_list.length" class="text-danger"> Such product does not exists </mat-option> </mat-autocomplete> </mat-form-field>
Step 2: Add the Display Function in Your Component (.ts)
Define a function that takes the selected product object and returns the name to display in the input field:
// Add this to your component class displayProductName(product: { product_id: number; name: string }): string { // Return the product name if the object exists, otherwise an empty string return product ? product.name : ''; }
Step 3: Access Both ID and Name from the Selected Value
Now your form control (product_name) will store the full product object. When you need to pass both the ID and name to your dialog, you can access them directly:
// Example: Retrieve the selected product from your form group const selectedProduct = this.yourFormGroup.get('product_name').value; if (selectedProduct) { const productId = selectedProduct.product_id; const productName = selectedProduct.name; // Use these values in your dialog logic here console.log('Selected Product ID:', productId); console.log('Selected Product Name:', productName); }
Bonus: Fixing Debounce Time (Optional)
I noticed your onSearchChange function includes debounceTime(200) but it’s not being applied correctly. To properly debounce your API calls and avoid excessive requests as the user types, adjust your code like this:
// First, import necessary RxJS operators and classes import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; import { Subject } from 'rxjs'; // In your component class private searchSubject = new Subject<string>(); ngOnInit(): void { this.searchSubject.pipe( debounceTime(200), // Wait 200ms after the last input event distinctUntilChanged() // Only trigger if the input value actually changed ).subscribe(value => { this.productService.search_Products(value).subscribe(data => { if (data) { this.product_list = data; } }); }); } onSearchChange(value: string): void { this.searchSubject.next(value); }
This will ensure your API is only called after the user stops typing for 200ms, improving performance.
内容的提问来源于stack exchange,提问作者pratik jaiswal

