I'm setting an invoice Angular page where lines are added dynamically, every line should have an own autocomplete input with other different inputs.How can i refer to each autocomplete input independently inside my component so i can use the right one inside my displayWith function ?
My question is similar to this one but i can't find the right answer there :(
HTML
<tr *ngFor="let ligneFacture of facture.lignesFacture; let i =index;">
<td width="5%" align="center">
<button type="button" class="button btn-primary"
style="border-radius: 50px;" disabled><span>{{i+1}}</span>
</button>
</td>
<td width="25%">
<form>
<mat-form-field>
<input type="text" class="form-control" matInput
(ngModelChange)="watchChangesArticle($event)"
(focus)="cursorFocusArticle($event)"
[matAutocomplete]="autoArticle"
[ngModelOptions]="{standalone: true}"
[(ngModel)]="ligneFacture.articleId">
<mat-autocomplete #autoArticle="matAutocomplete"
[displayWith]="displayFnArticle.bind(this)"
[autoActiveFirstOption]="true">
<mat-option *ngFor="let article of articles;"
[value]="article.id">
{{article.libelle}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
</td>
<td width="10%"><input type="text" class="form-control"
style="text-align: center"
[ngModelOptions]="{standalone: true}"
[(ngModel)]="ligneFacture.unite"/>
<td width="10%"><input type="number" class="form-control" #quantity
id="quantity{{i+1}}"
[ngModelOptions]="{standalone: true}"
[(ngModel)]="ligneFacture.quantite"/>
</td>
<td width="13%">
<div class="input-group">
<input type="number" class="form-control"
[ngModelOptions]="{standalone: true}"
[(ngModel)]="ligneFacture.tauxTva" readonly/>
<div class="input-group-append">
<span class="input-group-text">%</span>
</div>
</div>
</td>
<td width="15%"><input type="number" class="form-control"
[ngModelOptions]="{standalone: true}"
[(ngModel)]="ligneFacture.prixUnitaire" tabindex="-1"
[value]="updateChanges(ligneFacture)"
readonly/></td>
<td width="15%"><input type="number" class="form-control"
[ngModelOptions]="{standalone: true}"
[(ngModel)]="ligneFacture.prixTotal" tabindex="-1" readonly/>
</td>
<td>
<div>
<button type="button" class="btn btn-danger"
(click)="removeLine(ligneFacture)" tabindex="-1">
<span>[X]</span>
</button>
</div>
</td>
</tr>
<br>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td colspan="2" align="right">
<button type="button" class="btn btn-primary" (click)="addLine()">
<span>[+] Ajouter une ligne</span>
</button>
</td>
</tr>
TS:
export class FactureUpdateComponent implements OnInit {
@ViewChild('autoArticle') matAutocompleteArticle: MatAutocomplete;
//
//
displayFnArticle(item) {
const matOptions = this.matAutocompleteArticle.options.filter(x => x.value === item);
if (matOptions.length !== 0) {
setTimeout(() => {
const element = document.getElementById('quantity' + this.facture.lignesFacture.length);
element.focus();
}, 0);
return matOptions.map(x => x.viewValue)[0];
} else {
return this.facture.lignesFacture.filter(x => x.articleId === item).map(x => x.articleLibelle);
}
}
watchChangesArticle(event, ligneFacture: ILigneFacture) {
this.articleService.queryByKeyword(event, this.req).subscribe(
(res: HttpResponse<IArticle[]>) => {
ligneFacture.articles = res.body;
},
(res: HttpErrorResponse) => this.onError(res.message)
);
}
cursorFocusArticle(event, ligneFacture: ILigneFacture) {
if (event.target.value === '') {
this.articleService.queryByKeyword('', this.req).subscribe(
(res: HttpResponse<IArticle[]>) => {
ligneFacture.articles = res.body;
},
(res: HttpErrorResponse) => this.onError(res.message)
);
}
}
}
Expected result : inside the displayFnArticle function,i can access the autocomplete input of the current line
Actual result : im just getting access to the same first autocomplete input id which may be causing the following dysfunction
You can use template refs there. Docs: https://angular.io/guide/template-syntax#template-reference-variables--var-.
Example is here: https://stackblitz.com/edit/angular-template-ref-with-fn
So you have HTML like this:
<button *ngFor="let i of array" #ref (click)="doStuff(ref)" class="{{ 'a' + i }}">{{ 'a' + i }}</button>
And you handle this like this:
doStuff(instance: HTMLElement) {
console.log('>> stuff', instance.classList);
}
It is just an example with simple elements but you can do same with MatAutocomplete.