Issue
I am doing edit page in my project, so for default value i want to have data that was sent by server, i am trying to set default value from their docs but it doesnt work, what am i doing wrong?
here is my stackblitz
.ts
public manufacturerMultiFilterCtrl: FormControl = new FormControl();
protected _onDestroy = new Subject<void>();
public filteredManufacturers: ReplaySubject<any[]> = new ReplaySubject<any[]>(
1
);
set data(data: any[]) {
this.manuf = data;
// load the initial list
this.filteredManufacturers.next(this.data.slice());
}
constructor(private fb: FormBuilder) {}
@ViewChild('multiSelect', { static: true }) multiSelect: MatSelect;
ngOnInit() {
//chosen data
this.carDetail = {
manufacturer: 'manuf',
manufacturerId: 1,
};
this.updateEstimation = this.fb.group({
manufacturer: [this.carDetail.manufacturer],
});
this.updateEstimation.controls['manufacturer'].setValue(
this.carDetail.manufacturer
);
//all manufacturers
this.manuf = [
{
manufacturerId: 1,
name: 'manuf',
},
{
manufacturerId: 2,
name: 'manuf1',
},
];
this.filteredManufacturers.next(this.manuf);
}
ngAfterViewInit() {
this.setInitialValue();
}
protected setInitialValue() {
this.filteredManufacturers
.pipe(take(1), takeUntil(this._onDestroy))
.subscribe(() => {
console.log(this.multiSelect);
this.multiSelect.compareWith = (a: string, b: string) => a === b;
});
}
Solution
Here is a working stackblitz: https://stackblitz.com/edit/angular-13-starter-x-z434ak?file=src/app/app.component.ts
Issues boil down to the following:
- Make sure you using a formGroup to wrap your whole form itself
- Ensure that the compareWith function is comparing against the correct fields.
In the above I switched manufacturer to be the whole object, you would note however that there is a difference between the two objects it is comparing. I suspect this is due to differences between what you are actually setting as your source and the underlying representation of each item.
If you wanted to still just use the name directly then your compare with would look like so:
compareFunction(o1: any, o2: any) { console.log('o1 is: ', o1, o2); return o1.name == o2; }
Since o1 is your manuf object, and o2 is the just the string value of the name of the manufacturer. Really I think what bit you the most, and made this hard to follow, was the different object types that have some overlap, but are not the same. Your data source and individual item itself should be identical.
Here is a link to another stack blitz which has a very simple and succinct example of using compareWith: https://stackblitz.com/edit/angular-material-select-compare-with?embed=1&file=app/app.html
Edit: In case Stackblitz takes forever to load or access is lost since I didn't bother registering my github when I made the changes:
Html:
<div class="details align-items-center d-flex" [formGroup]="updateEstimation">
<mat-form-field appearance="fill" class="nusx">
<mat-select formControlName="manufacturer" [compareWith]="compareFunction" #multiSelect>
<mat-option>
<ngx-mat-select-search
formControlName="manufacturerMultiFilterCtrl"
[placeholderLabel]="'search...'"
[noEntriesFoundLabel]="'not found'"
>
</ngx-mat-select-search>
</mat-option>
<mat-option
*ngFor="let item of filteredManufacturers | async"
[value]="item"
>{{ item.name }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
TS:
import { Component, ViewChild, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { MatSelect } from '@angular/material/select';
import { ReplaySubject, Subject, take, takeUntil } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
manuf: any;
carDetail: any;
updateEstimation: FormGroup;
protected _onDestroy = new Subject<void>();
public filteredManufacturers: ReplaySubject<any[]> = new ReplaySubject<any[]>(
1
);
set data(data: any[]) {
this.manuf = data;
// load the initial list
this.filteredManufacturers.next(this.data.slice());
}
constructor(private fb: FormBuilder) {}
@ViewChild('multiSelect', { static: true }) multiSelect: MatSelect;
ngOnInit() {
//chosen data
this.carDetail = {
carId: 3,
registrationNumber: 'yyyyyyyy',
manufacturer: 'manuf',
manufacturerId: 1,
carModel: 'carmod',
carModelId: 1,
year: 2021,
vincode: 'yyyyyyyy',
};
console.log('overall data', this.filteredManufacturers);
console.log('manufacturer oninit: ', this.carDetail.manufacturer);
this.updateEstimation = this.fb.group({
manufacturer: [this.carDetail],
manufacturerMultiFilterCtrl: [this.carDetail.manufacturer],
});
//all manufacturers
this.manuf = [
{
manufacturerId: 1,
name: 'manuf',
carModels: [
{
carModelId: 1,
name: 'carmod',
},
{
carModelId: 2,
name: 'Carmod1',
},
],
},
{
manufacturerId: 2,
name: 'manuf1',
carModels: [
{
carModelId: 3,
name: 'Carmod2',
},
],
},
];
this.filteredManufacturers.next(this.manuf);
}
compareFunction(o1: any, o2: any) {
console.log('o1 is: ', o1, o2);
return o1.name == o2.manufacturer && o1.manufacturerId == o2.manufacturerId;
}
}
Answered By - SomeStudent

0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.