Angular AutoComplete needs pass its object value and displays its object label - javascript

<input
#autoInput
type="text"
aria-label="Number"
matInput
[matAutocomplete]="auto"
[formControlName]="field.model"
[id]="field.model"
/>
<mat-autocomplete
#auto="matAutocomplete"
(optionSelected)="onUpdate(field)"
[displayWith]="displayFn"
>
<mat-option
*ngFor="
let option of getFiltered(
options[field.model],
autoInput
)
"
[value]="option.value || option"
>
{{ option?.label || option }}
</mat-option>
</mat-autocomplete>
My requirement was to show the selected label in the Input Box and get the Selected value to the .ts file. but if I selected anything from the option instead of the label its 'value' is displaying on the autocomplete input box. passing by entire object by '[value]="option"' '[displayWith]="displayFn"' I can solve the Displaying issue but on .ts file the entire object is receiving. I dont need that. in .ts file 'option.value' must reach. how can I solve the issue

Related

Assign custom values to ID and FOR properties of the checkbox and label resulted from ngFor loop to populate list

My problem is two-fold:
I need to assign to each checkbox and label for checkbox unique ID and FOR value so each label corresponds to its according checkbox.
Finally I need to capture which fields have been checked (I'm thinking somehow in a map, key being the country and value true/false) and create an SQL query which I can then send to the backend to retrieve the filtered result.
Something like this ?
<ng-container *ngFor="let country of countries$ | async">
<input type="checkbox" [value]="country" id="cb-{{ country }}">
<label for="cb-{{ country }}">{{ country }}</label>
</ng-container>
countries$ = this.powerPlantService.getPowerPlantCountryNames().pipe(shareReplay(1));
Here is the answer for unique ID and FOR value.
And here is how I capture the checked items and use them in a query:
What I did was capture the check/uncheck and the name of the country in the countryNameAndCheckBoxStatus method inside the HTML component. Process these in an array inside the angular component and return the array so it can be processed further down the road into an sql query.

Angular Material Autocomplete - how to select option

I am using Angular material autocomplete and I am trying to select value using #Input and form control. Almost everything is working fine. I am setting value using input like this:
#Input() set startingPointValue(value) {
this.control.setValue(value, { emitEvent: false });
this.resizeInput();
}
And the value of the input is properly set but when I open autocomplete, an option which should be selected don't have mat-selected class so basically there is no indication which option was selected and this is confusing. When I click same option again class is added.
Is there a way to do that using setValue or I need to use something else?
This is my autocomplete HTML:
<mat-form-field class="starting-point-filter-container">
<mat-label>{{ label }}</mat-label>
<input
id="inputStartingPoint"
#startingPointInput
matInput
placeholder="Type to filter results"
type="text"
[formControl]="control"
[matAutocomplete]="startingPointAutocomplete"
spellcheck="false"
/>
<mat-icon class="starting-point-icon--dropdown">arrow_drop_down</mat-icon>
</mat-form-field>
<mat-autocomplete
#startingPointAutocomplete="matAutocomplete"
[displayWith]="displayName"
(opened)="scrollToSelected()"
>
<perfect-scrollbar class="select-scrollbar" [config]="scrollBarConfig" #scrollFilterContainer>
<mat-optgroup
*ngFor="let group of groups"
[label]="group.name"
[class.mat-optgroup-no-label]="!group.name"
class="starting-point-group-container"
#scrollToContainer
>
<mat-option *ngFor="let option of filteredOptions | async" [value]="option">
{{ option.id }}
</mat-option>
</mat-optgroup>
</perfect-scrollbar>
</mat-autocomplete>
Any help will be appreciated
Edit:
I created StackBlitz with autocomplete: https://stackblitz.com/edit/angular-ivy-mqwwky. You can inspect option number 2 after init. There is no class .mat-selected on it. You need to click it manually to set it properly. Question is how to do that during init?

Patch value on form array not setting value on material multiple select

I am trying to patch value an array of ids from Firestore into a mat-select with multiple options. I am looping through the array and creating a new form control for each id and then using the reactive form push method to add to the formArray. Like so:
patchValueForm(portfolio: any) {
this.formGroup.patchValue(portfolio);
for (const id of portfolio.property_ids) {
const control = new FormControl(id);
if (!this.property_ids.getRawValue().includes(id)) {
this.property_ids.push(control);
}
}
console.log(this.formGroup.getRawValue()); }
This does seem to patch the value into the form as shown from the console log:
The problem that I am having is that its then not pre populating the material select shown here:
The HTML that I am using for this part is:
<mat-form-field appearance="outline">
<mat-select [formArrayName]="'property_ids'" multiple>
<mat-option *ngFor="let property of properties; let i = index"
(onSelectionChange)="updatePropertyIdArray(property.property_id)" >
{{property?.address?.first_line_address}}
</mat-option>
</mat-select>
<mat-error>Please select at least one property</mat-error>
</mat-form-field>
I have searched everywhere online and tried multiple different methods, but still ca not seem to populate the select. Has anyone experienced this before?
I would just use a simple formControl instead of the formArray in the mat select. The formControl holds the selection array and u can use formControlName.
<mat-form-field appearance="outline">
<mat-select [formControlName]="'property_ids'" multiple>
<mat-option *ngFor="let property of properties; let i = index" [value]="property.property_id"
(onSelectionChange)="updatePropertyIdArray(property.property_id)" >
{{property?.address?.first_line_address}}
</mat-option>
</mat-select>
<mat-error>Please select at least one property</mat-error>
</mat-form-field>
You also need the value binding in the mat option to make the select work properly.

Passing placeholders and labels to common input components, Angular 2+

I have made a common reusable input field component. Now, the issue is that the placeholders and labels for this input component are static. How can I pass place holders and labels dynamically for the component i am calling this component from!
<mat-form-field appearance="outline" class="common-location">
<mat-label>**Search By Location**</mat-label> // {{label that i would pass}}
<input matInput type="text" placeholder="**{{placeHolder}}**" formControlName="location" name="location" aria-label="Location" [matAutocomplete]="auto"> //placeholder that should be passed
<mat-autocomplete #auto="matAutocomplete" [displayWith]="location">
<mat-option *ngFor="let places of predictions" [value]="places.description">
<span>{{places.description}}</span>
</mat-option>
</mat-autocomplete>
<mat-error>Please enter location of job.</mat-error>
</mat-form-field>
And I am calling this component from outside as:
<app-autocomplete (formReady)="addFormControl('location', $event)" [placeHolder]="Location"></app-autocomplete>
trying to send placeholder and trying to bind in the common component not working for me.
I am new to this, I have worked with Ember and I know that we can pass data the same way as I am trying to pass here and then binding the same works there. How does it work in Angular?

How to pass whole object to input from md-autocomplete angular 4

Generally i have an object of objects -> filteredDrivers.
Single object looks like this:
DRIVER_ID: 99
DRIVER_NAME: "JOHN SNOW"
which i'm using in md-autocomplete:
<md-input-container>
<input type="text"
name="driver"
mdInput
[mdAutocomplete]="auto"
placeholder="Driver"
ngModel
>
</md-input-container>
<md-autocomplete #auto="mdAutocomplete">
<md-option *ngFor="let driver of filteredDrivers| async" [value]="driver"
ngDefaultControl>
{{ driver.DRIVER_NAME}}
</md-option>
</md-autocomplete>
And i want to pass whole object by submitting a form but in input i want to view just driver.DRIVER_NAME.
If i pass whole driver like [value]="driver" in input i see [object Object]
and form submit gives me full object
but when i go with [value]="driver.DRIVER_NAME" i can see what i want - JOHN SNOW but form submit gives me only driver.DRIVER_NAME
How can i pass whole object by submitting the form and see only driver.DRIVER_NAME property in input?
It's clearly documented in the Angular Material docs for
Autocomplete.
Specifically:
Setting separate control and display values
If you want the option's control value (what is saved in the form) to
be different than the option's display value (what is displayed in the
actual text field), you'll need to set the displayWith property on
your autocomplete element. A common use case for this might be if you
want to save your data as an object, but display just one of the
option's string properties.
To make this work, create a function on your component class that maps
the control value to the desired display value. Then bind it to the
autocomplete's displayWith property.
<md-input-container>
<input type="text" mdInput [formControl]="myControl" [mdAutocomplete]="auto">
</md-input-container>
<md-autocomplete #auto="mdAutocomplete" [displayWith]="displayFn">
<md-option *ngFor="let option of filteredOptions | async" [value]="option">
{{ option.name }}
</md-option>
</md-autocomplete>

Categories