Fel
Fel

Reputation: 4818

Angular 7 and HTML selects issue

I have an Angular 7 reactive form which have, among others, the following fields:

<div class="ui-grid-col-2">
    <select formControlName="network_interface" (change)="onInterfaceChange($event.target.value)">
        <option *ngFor="let ifc of interfaces; let idx = index;" [value]="ifc.id">
            {{ ifc.id }} - {{ ifc.name }}
        </option>
    </select>
</div>
<div class="ui-grid-col-2">
    <select formControlName="interface_ip">
        <option *ngFor="let obj of interfacesIps; let idx = index;" [value]="obj.id">
            {{ obj.name }}&nbsp;({{obj.address}})
        </option>
    </select>
</div>

Basically, it allows the user to select an interface and interface IP from 2 lists, stored in the arrays interfaces and interfacesIps.

One combo is 'tied' to the other, so if I select an interface the other combo must show its internal IP addresses. This is done in the onInterfaceChange event handler, fired by the change event. This is what I do:

onInterfaceChange(interfaceId : any): void {
    // NOTE: this.interfaces[INDEX].ips is an array of IP addresses
    this.interfacesIps = this.interfaces[interfaceId].ips;
}

This works, and the IP list is refreshed whenever I change the selected interface, BUT I've realized that the form control associated to the combo (interface_ip) is not updated. It should be the first IP in the list, but I keeps the old value, until I change to another IP.

I've fixed this by manually changing the form control value on the event handler above, but I'd like to know if there's a way to do it automatically.

Thanks in advance,

Upvotes: 2

Views: 167

Answers (4)

Fel
Fel

Reputation: 4818

Thanks for the suggestions! This is what I've done:

I've changed the [value] for [ngValue]. Now, the change event on the dropdown isn't fired anymore, so I used the valueChanges observable on the network interfaces form control to load the appropriate addresses when it changes:

this.formModel.controls['network_interface'].valueChanges((value) => {
  // Update the addresses on interface change
  this.interfacesIps = this.interfaces[value].ips;
});

Now all works as expected.

Thanks everyone!

Upvotes: 0

Robert
Robert

Reputation: 564

So if you need a dependend dropdown, you just need to populate the first with the data as you already did, to populate the second you need to use a propriety of reactive form called valueChanges, it's listen for changes of that formControl.

this.network_interface.valueChanges.subscribe((selectedValue) => {
    /* 
     Here you select wich data to put in other select based on selectedValue
    */
}); 

Upvotes: 1

Borad Akash
Borad Akash

Reputation: 804

I think you need to change [value] to [ngValue] inside option tag.

Select tag doesn't have any value but option tag does have.so if you want to bind option's value in select tag, you need to use angular's SelectControlValueAccessor which basically bind the option's value to select tag.

You can use SelectControlValueAccessor by using ngValue inside option tag.

You need to change your code as following:

<div class="ui-grid-col-2">
    <select formControlName="network_interface" (change)="onInterfaceChange($event.target.value)">
        <option *ngFor="let ifc of interfaces; let idx = index;" [ngValue]="ifc.id">
            {{ ifc.id }} - {{ ifc.name }}
        </option>
    </select>
</div>
<div class="ui-grid-col-2">
    <select formControlName="interface_ip">
        <option *ngFor="let obj of interfacesIps; let idx = index;" [ngValue]="obj.id">
            {{ obj.name }}&nbsp;({{obj.address}})
        </option>
    </select>
</div>

Upvotes: 1

Shane
Shane

Reputation: 669

you can subscribe to the network_interface form control value change as follows;

this.network_interface.valueChanges.subscribe(val => {
// your code here
});

you may also want to change [value] to [ngValue] if you're working with non string values

Upvotes: 1

Related Questions