I'm trying to make a list of inputs mat autocomplete but I have an error of types in FormControl and duplicates data. I want to do dynamic mat autocompletes to set The list of items to later post. By having the name myControl
for the input, as I add inputs to the list of items, they are overwritten. I want to know how to generate ids and access them in ts to manage the data.
I leave you the code and images so you can see the problem.
I have tried to dynamically create the formControl or a formControlName but I still don't understand how to generate it in the TS.
<!-- Modal body -->
<div class="grid grid-cols-6 xl:grid-cols-6 gap-4 px-4 py-4">
@for (i of items; track i) {
<div class="w-full h-20 rounded-xl col-span-2">
<mat-form-field class="example-full-width">
<mat-label>Producto</mat-label>
<input type="text"
placeholder="Selecciona"
aria-label="Producto"
matInput
[formControl]="myControl"
[matAutocomplete]="auto">
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
<mat-option value=""></mat-option>
@for (dbi of filteredOptions | async; track dbi) {
<mat-option (onSelectionChange)="changeSelection(i.id)" id="{{i.id}}" [value]="dbi.name">{{dbi.name}}</mat-option>
}
</mat-autocomplete>
</mat-form-field>
</div>
items = [{id: 0, name: '', units: 0, price: 0, totalConcept: 0}];
data = [];
dbItems:any = [];
apiService = inject(ApiService);
myControl = new FormControl('');
filteredOptions!: Observable<any[]>;
lastOptionIdSelected:number = 0;
lasItemAdded: any = {};
constructor(public dialogRef: MatDialogRef<BudgetDetailsComponent>){}
ngOnInit() {
if(this.data.length > 0){
this.items = this.data;
}
this.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
map(value => this._filter(value || '')),
);
}
onClose(): void {
if(this.items[this.items.length - 1].totalConcept == 0){
this.items.pop();
}
this.dialogRef.close({data: this.items});
}
addItem(id:number){
let unitsInput = document.getElementById('units'+id) as HTMLInputElement;
this.items[id].name = this.lasItemAdded.name;
this.items[id].units = parseFloat(unitsInput.value);
this.items[id].price = parseFloat(this.lasItemAdded.priceU);
this.items[id].totalConcept = parseFloat(unitsInput.value) * parseFloat(this.lasItemAdded.priceU.value);
this.items.push({id: id+1, name: '', units: 0, price: 0, totalConcept: 0});
}
changeSelection(id: number){
this.lastOptionIdSelected = id;
}
private _filter(value: any): any[] {
const filterValue = value.toLowerCase();
let itemSelected = this.dbItems.find((item:any) => item.name === value)!;
if(itemSelected !== undefined) {
let priceElement = document.getElementById(`priceTD${this.lastOptionIdSelected}`)! as HTMLInputElement;
priceElement.value = itemSelected.priceU;
}
this.lasItemAdded = itemSelected;
return this.dbItems.filter((option:any) => option.name.toLowerCase().includes(filterValue));
}