1

Seriously stumped here. I have two reactive forms in an Angular project.

Both have a select control with options stored in class variables.

One form uses simple option strings for employee options, as in:

["Dan Smith", "Mark Johnson", etc.]

The other form uses objects, as in:

[
  {
    value: "Dan Smith",
    selected: false,
    hidden: false
  },
  ...
]

Stackblitz example: https://stackblitz.com/edit/angular-nks51y

In the example I have buttons for adding new random options, and setting a random selected option.

The buttons work on the form which uses simple strings, but don't work with the form using objects {}.

Additionally, the default value isn't set with the object form.

I know I'm missing something, but can't figure out what.

2 Answers 2

2

There are two mistakes in your code:

  1. you should never set the selected attribute of the select element. The whole point of the binding is that the option that is selected is the one set as the value of the form control. The model is the source of truth, not the view

  2. The selected value (i.e. the value of the FormControl) is an object: the employee object itself. But the ngValue used in the template is name.value, i.e. a string which is the value of the employee object. An employee object can't be === to its value property.

So the code should be:

<select formControlName="employeeName">
  <option *ngFor="let employee of employeeNameObjectOptions" [ngValue]="employee" [hidden]="employee.hidden">
    {{ employee.value }}
  </option>                
</select> 

Note that I chose to rename name to employee since that's what the variables refereces: an employee, not a name. Good naming helps a lot to figure out mistakes.

Your fixed demo: https://stackblitz.com/edit/angular-pundfg?file=src%2Fapp%2Fapp.component.html

Sign up to request clarification or add additional context in comments.

2 Comments

JB Nizet, thank you for taking the time answer this clearly, thoroughly, and give an example. Could you touch a little on the use [compareWith] ? In searching for a solution to this problem I found multiple references to it, but don't quite understand the need for it.
It allows using something other than strict equality (i.e. ===) to test if the value of the option should be considered equal to the value of the form control. Imagine you get an object using an http request, containing the employee of the month. And you make another http request to get all the employees of the company to populate the select box. Even though the employee of the month is, functionally, one of the employees of the company, they're different JavaScript objects. compareWith can be used, for example, to consider two employees equal if they have the same ID.
2

The ngValue for your select option is a string [ngValue]="name.value" and type does not match when you are setting an object to it.

<option *ngFor="let name of employeeNameObjectOptions" [selected]="name.selected" [ngValue]="name" [hidden]="name.hidden">
        {{ name.value }}
</option>  

Comments

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.