3

I have 2 dropdowns and I populate 2nd dropdown based on the value of dropdown 1. I have scenario to Edit and populate the dropdown values based on the grid.

enter image description here

private populateContacts(relationship: Relationship) {
        this.getContacts(relationship.businessAreaId);
        this.selectedContact = this.contacts.find(contact => contact.id === relationship.contacts[0].id);
    }

    private getContacts(businessAreaObjorId) {
        if (businessAreaObjorId === NaN)
            businessAreaObjorId = businessAreaObjorId.id;
        this.businessAreaService.getContacts(businessAreaObjorId)
            .subscribe(
            contacts => this.contacts = contacts,
            error => this.errorMessage = error);
    }

Html is below

<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)="getContacts($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>

When I click on Edit link onEdit method is called and selects/assigns the values but fails on selction of contacts.

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.populateContacts(relationship);
}

private populateContacts(relationship: Relationship) {
    this.getContacts(relationship.businessAreaId);
    this.selectedContact = this.contacts.find(contact => contact.id === relationship.contacts[0].id);
}

It fails on the line when i am trying to find contact in contacts array.

enter image description here

I assume the reason is service.getcontacts is http call and it takes time and when i am trying to find the contact object in this.contacts array which is undefined.

Is there a way to wait for getContacts in populateContacts method?

Edit 1:

my new code looks like this

private populateContacts(relationship: Relationship) {
        //TODO: find a way to use 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 getContacts(businessAreaObj) {
    this.businessAreaService.getContacts(businessAreaObj.id)
        .subscribe(
        contacts => this.contacts = contacts,
        error => this.errorMessage = error);
}

Edit 2:

@Gunter' solution works for Edit case but if i manually select dropdown value on BA it does not load contacts in contacts dropdown.

enter image description here

2
  • Could you please show your html code for your edit button? Commented Aug 25, 2016 at 10:19
  • please check the question for update html Commented Aug 25, 2016 at 10:31

1 Answer 1

1

You need to return the Observable. For this you must not call subscribe()

private getContacts(businessAreaObjorId) {
    if (businessAreaObjorId === NaN)
        businessAreaObjorId = businessAreaObjorId.id;
    return this.businessAreaService.getContacts(businessAreaObjorId)
        .catch(error => this.errorMessage = error)
        .map(
        contacts => this.contacts = contacts);

    }
}

then you can call it, get an Observable you can subscribe to, and in the callback you call the follow-up code:

private populateContacts(relationship: Relationship) {
    this.getContacts(relationship.businessAreaId)
    .subscribe(val => this.selectedContact = this.contacts.find(contact => contact.id === relationship.contacts[0].id));
}
Sign up to request clarification or add additional context in comments.

9 Comments

thanks for your response Gunter, this.businessAreaService.getContacts is already observable. its an http call. i have 2 scenario here. 1. populate contacts dropdown based on BA value 2. select value when Edit is clicked. I do not require observable for 1st scenario. its like i am calling same method for both cases. but let me try your solution first :)
as expected above solution works perfectly well for Edit case but when i am creating new record and select value from BA it does not populate contacts dropdown because i am not subscribing on change...I think getContacts should subscribe and in populate contacts i will call the service directly?I was trying to avoid another http call and use the same array this.contacts. is there a way?
That's a bit complex to follow all these details. Sounds like stackoverflow.com/questions/36271899/…
sorry for weird explanation. when i call getcontacts() I assign my array to this.contacts. I just want to use the same array in populateContacts() method.
the contacts from getContacts are forwarded to the subscriber. val in populateContacts() will be the same array (the one returned from .map(contacts => this.contacts = contacts) (the result of this.contacts = contacts will be contacts)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.