3

When I select an item in the following matAutocomplete formControl, I always get the ID, instead of the value, shown in the drop-down.

When I change [value]="baseCoin.ID" to [value]="baseCoin.Abbr", the correct string is shown when I select an item, however, I need the (ngModelChange) event to return the baseCoin.ID to a method, instead of the baseCoin.Abbr.

<mat-form-field>
    <input matInput placeholder="Base Coin" aria-label="Base Coin" [matAutocomplete]="basecoin" [formControl]="baseCoinCtrl" [(ngModel)]="newTrade.BaseCoin.Abbr" (ngModelChange)="populateMarketCoins( $event )">
    <mat-autocomplete #basecoin="matAutocomplete">
        <mat-option *ngFor="let baseCoin of filteredBaseCoins | async" [value]="baseCoin.Abbr">
            {{baseCoin.Abbr | uppercase}}
        </mat-option>
    </mat-autocomplete>
</mat-form-field>

Am I missing something?

Help is appreciated. Thanks.

user3004118
  • 125
  • 3
  • 13

4 Answers4

9

Take a look at "Setting separate control and display values" from the docs. The autocomplete has an @Input() displayWith which is a "Function that maps an option's control value to its display value in the trigger".

displayFn(baseCoin) {
  return baseCoin ? baseCoin.Abbr : undefined;
}
<mat-autocomplete #basecoin="matAutocomplete" [displayWith]="displayFn">
  <mat-option *ngFor="let baseCoin of filteredBaseCoins | async" [value]="baseCoin">
      {{baseCoin.Abbr | uppercase}}
  </mat-option>
</mat-autocomplete>

I would also like to add that Autocomplete has an

@Output() optionSelected: EventEmitter<MatAutocompleteSelectedEvent>

property, which is an "Event that is emitted whenever an option from the list is selected". The Select also has a similar output. onSelectionChanged however, is an "Event emitted when the option is selected or deselected."

andbjer
  • 554
  • 2
  • 9
1

you need to use two form control for that.

check this example

<md-input-container class="full-width">
                                                <input mdInput placeholder="Location *" [mdAutocomplete]="autoLocation"
                                                       #searchLocation
                                                       formControlName="location_name"
                                                       id="selLocation"
                                                       (keyup)="onChangeLocationName()">
                                            </md-input-container>
                                            <md-autocomplete #autoLocation="mdAutocomplete">
                                                <md-option
                                                        *ngFor="let location of locations | search: searchLocation.value"
                                                        [value]="location.name"
                                                        (onSelectionChange)="onSelectedLocation($event.source.selected, location.id)">
                                                    {{ location.name }}
                                                </md-option>
                                            </md-autocomplete>

component

onSelectedLocation(isSelected: boolean, locationId: number): void {
    if (isSelected) {
        setTimeout(() => {
            this.userForm.patchValue({location_id: locationId});
            this.userForm.get('location_name').setErrors(null);
            this.selectedLocationName = this.userForm.value.location_name;
        }, 200);
    }
}

you need to also create search pipe

Shailesh Ladumor
  • 7,052
  • 5
  • 42
  • 55
0

(ngModelChange) now triggers populateMarketCoins() without returning the $event.

(onSelectionChange)="setBaseCoinID( baseCoin.ID )" was added to mat-option.

<mat-form-field>
    <input matInput placeholder="Base Coin" aria-label="Base Coin" [matAutocomplete]="basecoin" [formControl]="baseCoinCtrl" [(ngModel)]="newTrade.BaseCoin.Abbr" (ngModelChange)="populateMarketCoins()">
    <mat-autocomplete #basecoin="matAutocomplete">
        <mat-option *ngFor="let baseCoin of filteredBaseCoins | async" [value]="baseCoin.Abbr" (onSelectionChange)="setBaseCoinID( baseCoin.ID )">
            {{baseCoin.Abbr | uppercase}}
        </mat-option>
    </mat-autocomplete>
</mat-form-field>

Metghod setBaseCoinID() sets an instance variable which is called by method populateMarketCoins().

So far this works.

However, a level higher, where Base Coins are selected based on a selected Exchange, I want to use a mat-select in a similar way, like this:

<mat-form-field>
    <mat-select placeholder="Exchange" name="Exchange" [(ngModel)]="newTrade.Exchange.Title" (ngModelChange)="populateBaseCoins()">
        <mat-option *ngFor="let exchange of exchanges" [value]="exchange.Title" (onSelectionChange)="setExchangeID( exchange.ID )">
            {{exchange.Title}}
        </mat-option>
    </mat-select>
</mat-form-field>

I found out that (onSelectionChange) is fired every time (also on initialization) for every mat-option, so method setExchangeID always sets the last in array exchanges.

Any idea what should be changed?

user3004118
  • 125
  • 3
  • 13
0

You need to use displayWith attribute. You can get more info and examples showing its usage in the official doc site: https://material.angular.io/components/autocomplete/overview#setting-separate-control-and-display-values

Sagar M
  • 1,168
  • 13
  • 10