1

I am using Angular reactive form in my application. I would like to set multiple values to a multiple select form control.

mycomponent.html

<select id="placeType" 
        class="form-control" 
        [multiple]="true" 
        style="height:200px" 
        formControlName="kalase">
  <option value="" selected="selected" disabled>Select Place Type</option>
  <option *ngFor="let kalase of types" [value]="kalase" [innerHtml]="kalase"></option>      
</select>

mycomponent.ts

types: string[] = ["BAR", "CAFE", "RESTAU", "hotels", "club"];

this.placeForm = this.formBuilder.group({
  kalase: [[this.types[1], this.types[3]]]
});

The problem is that the only selected value in select control is the fourth item of types array("hotels"). Can anyone tell me what I am doing wrong?

5
  • Why are you setting kalase to an array of an array of arrays? Maybe the code should be kalase: [this.types[1], this.types[3]]? Remove the first inner array. Too many square brackets? Commented Sep 15, 2018 at 19:42
  • I have tried it also...no working either.. Commented Sep 15, 2018 at 19:45
  • your code is correct, you should multi select by pressing control key when clicking options. (ctrl + left click) Commented Sep 15, 2018 at 21:10
  • Easiest way to help people... helping you is to make a repro on stackblitz. Commented Sep 15, 2018 at 22:10
  • @Fartab the expected behaviour is "CAFE" and "hotels" already been selected according to my code.. Commented Sep 16, 2018 at 7:00

1 Answer 1

6

SHORT ANSWER

Do not use property binding (brackets []) for multiple property:

<select id="placeType" 
        class="form-control" 
        multiple
        style="height:200px" 
        formControlName="kalase">

  <option value="" selected disabled>Select Place Type</option>
  <option *ngFor="let kalase of types" 
          [value]="kalase" 
          [innerHtml]="kalase"></option>
</select>

LONGER ANSWER

Multiple select and option are Angular directives. select directive iterates over options and decides whether select it or not:

this._optionMap.forEach(optionSelectedStateSetter);

which calls internal option's function _setSelected:

/** @internal */
_setSelected(selected: boolean) {
  this._renderer.setProperty(this._element.nativeElement, 'selected', selected);
}

In case of <select [miltiple]="true" ..., during this iteration, multiple property is not yet rendered on 'select' element (Angular did not evaluate it yet), thus select element is treated as single and only last option (in the order of types array) is set as selected.

Only after this iteration multiple property will be rendered by Angular and from this point on, the select element will act properly. So even running:

setTimeout(this.placeForm.get('kalase').setValue(this.placeForm.value.kalase));

would "fix" the problem, because reactive form's model is correct and select element now is multiple.

To see incorrect options value, you can run in console:

[...document.querySelector('#placeType')].map(x => `${x.value}: ${x.selected}`)

which will give you:

'': false
'BAR': false
'CAFE': false
'RESTAU': false
'hotels': true
'club': false

In case of <select multiple ..., the element from the very beginning acts as multiple, thus setting option as selected indeed selects them.

Now, running previous debug query will give:

'': false
'BAR': false
'CAFE': true
'RESTAU': false
'hotels': true
'club': false

If for any reason, you need multiple property be conditional, I would recommend to use *ngIf or setting default value or values using setTimeout along with reactive form's model (as I already demonstrated)

STACKBLITZ

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

2 Comments

I don't understand why all the tutorials suggest using FormArray and formArrayName if this solution is way easier.
you do not need FormArray if your model is one dimensional list of primitives (like [1, 3, 6, 8] or ['aaa', 'bbb', 'ccc'] for example). You also can use third party libs' multiselects for this and explore their reactive form examples: material.angular.io/components/select/examples, primefaces.org/primeng/showcase/#/multiselect, etc...

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.