I am faced with a scenario where I need to populate the values of the second dropdown based on the selection made in the first dropdown. This requirement arises during editing, especially when populating dropdown values based on grid data.
https://i.sstatic.net/KlruP.png
private loadContacts(relationship: Relationship) {
this.fetchContacts(relationship.businessAreaId);
this.selectedContact = this.contacts.find(contact => contact.id === relationship.contacts[0].id);
}
private fetchContacts(businessAreaObjectOrId) {
if (businessAreaObjectOrId === NaN)
businessAreaObjectOrId = businessAreaObjectOrId.id;
this.businessAreaService.getContacts(businessAreaObjectOrId)
.subscribe(
contacts => this.contacts = contacts,
error => this.errorMessage = error);
}
The following is how the HTML looks like:
<tr *ngFor="let relationship of relationships">
<td>{{relationship.supplierName}}</td>
<td>{{relationship.businessArea}}</td>
<td>{{relationship.contacts[0].name}}</td>
<td><a href="javascript:void(0)" (click)="onEdit(relationship)">Edit</a></td>
</tr>
<tr class="active">
<td>
<select class="form-control" name="supplier" required
[(ngModel)]="selectedSupplier" #supplier="ngModel">
<option *ngFor="let supplier of suppliers" [ngValue]="supplier">{{supplier.name}}</option>
</select>
<div [hidden]="supplier.valid || supplier.pristine" class="alert alert-danger">
Supplier is required
</div>
</td>
<td>
<select class="form-control" name="businessArea" required
[(ngModel)]="selectedBusinessArea" #businessArea="ngModel" (ngModelChange)="fetchContacts($event)">
<option *ngFor="let businessArea of businessAreas" [ngValue]="businessArea">{{businessArea.name}}</option>
</select>
<div [hidden]="businessArea.valid || businessArea.pristine" class="alert alert-danger">
Business Area is required
</div>
</td>
<td>
<select class="form-control" name="contact" required
[(ngModel)]="selectedContact" #contact="ngModel">
<option *ngFor="let contact of contacts" [ngValue]="contact">{{contact.name}}</option>
</select>
<div [hidden]="contact.valid || contact.pristine" class="alert alert-danger">
Contact is required
</div>
</td>
<td>
<input type="button" value="Add" class="btn btn-default" (click)="onSubmit()" [disabled]="!factoryRelationshipForm.form.valid" />
</td>
</tr>
The issue occurs when selecting an item from the contacts dropdown after clicking the Edit link.
private onEdit(relationship: Relationship): void {
relationship.inEditMode = true;
this.selectedSupplier = this.suppliers.find(supplier => supplier.id === relationship.supplierId);
this.selectedBusinessArea = this.businessAreas
.find(businessArea => businessArea.id === relationship.businessAreaId);
this.loadContacts(relationship);
}
private loadContacts(relationship: Relationship) {
this.fetchContacts(relationship.businessAreaId);
this.selectedContact = this.contacts.find(contact => contact.id === relationship.contacts[0].id);
}
The issue arises at a particular point while trying to find a contact within the contacts array.
https://i.sstatic.net/MamMs.png
This problem might be due to the asynchronous nature of the service.getcontacts HTTP call, which causes delays in loading the contacts data into the contacts array resulting in "undefined".
Is there any way to implement a delay or wait for the getContacts method within the populateContacts function?
Edit 1:
My revised code implementation:
private loadContacts(relationship: Relationship) {
//TODO: Implement a mechanism to utilize this.contacts/getContacts
this.businessAreaService.getContacts(relationship.businessAreaId)
.subscribe(val => {
console.log(val);
this.contacts = val;
this.selectedContact = this.contacts.find(contact => contact.id === relationship.contacts[0].id)
});
}
private fetchContacts(businessAreaObj) {
this.businessAreaService.getContacts(businessAreaObj.id)
.subscribe(
contacts => this.contacts = contacts,
error => this.errorMessage = error);
}
Edit 2:
@Gunter's solution works well for the Edit case, but manual selection of a value in the BA dropdown does not trigger loading the contacts in the contacts dropdown.