Angular select option with selected attribute not working
Asked Answered
P

3

18

Using Angular 4, I have a html template and I want a selection box with two options. One of those options should be pre-selected by default.

<select name="rate" #rate="ngModel" ngModel required>
    <option selected value="hr">hr</option>
    <option value="yr">yr</option>
</select>

Details:

I assign #rate="ngModel" so that I can reference the value somewhere else in the template, in a conditional statement or with interpolation {{rate.value}}. For that to work I simply add ngModel to the tag. I'm not binding to anything in the component class as this control is only used to provide it's value to another control in the same template.

Issue:

In Chrome, and Microsoft Edge, the box is empty, no default value selected. If I get rid of #rate="ngModel" ngModel it works. However, I need the reference to rate.value.

I tried various combinations of ngValue, value, [ngValue], [value], but I'm not trying to bind the value to a model and I'm not using a ngFor loop. There is no further styling on the select box either.

Pubescent answered 13/10, 2017 at 17:57 Comment(6)
Doesn't just <select [(ngModel)]="rate" required > work?Hollis
@Vega, It's not a two-way binding so the [()] syntax shouldn't be used in this case. I believe.Pubescent
This didn't work and I need the template variable #rate="ngModel" so that I can reference this elsewhere in the template form. I'm also not trying to call an event. I've edited the details of my post to hopefully better describe the use case.Pubescent
That looks like what I'm trying to accomplish, and it does start with the option selected. But, after trying that link and trying it in my code I noticed that {{rate.value}} doesn't update.Pubescent
That's kind of normal as there is no two way binding, but it's updated. Check the updated demoHollis
Let us continue this discussion in chat.Pubescent
H
10

If you don't wish to have a two-way binding, you can set ngModel to the 'default' value and with the template local variable get the selected value:

<select #rate ngModel="hr">
    <option selected value="hr">hr</option>
    <option value="yr">yr</option>
</select>

<p *ngIf="rate.value == 'hr'">hr</p> 
<p *ngIf="rate.value == 'yr'">yr</p>

{{rate.value}}

DEMO

Hollis answered 13/10, 2017 at 21:57 Comment(3)
Thank You! I'd been reading through other ways of doing this and they just weren't working. The docs for Angular 5 pipes show it as [(ngModel)]='rate' which would work if I were populating the options dynamically and all of the stuff that comes with that. But for only two or three hard coded options this works. And it is so simpler conceptually. This is something so basic and simple I was surprised at the convoluted suggestions/fixes.Mcconaghy
Be careful, this is now deprecated with v7 if you are using reactive forms: angular.io/api/forms/FormControlName#use-with-ngmodelVermeil
@rynop, no, even with previous versions, it's better to not mix reactive forms and ngModel. But the OP doesn't use it anyway and my exemple either :)Hollis
C
18

When you use ngModel, the state is handled internally and any explicit change applied to the attributes just gets ignored. In your example, you are setting the selected property of option, but you are also providing a (void) ngModel to your select, so Angular expects that the state of the select is provided within the ngModel.

Briefly, you should leverage on your ngModel rather than setting the selected property:

<select 
    name="rate" 
    #rate="ngModel" 
    [(ngModel)]="yourModelName" 
    required
>
    <option value="hr">hr</option>
    <option value="yr">yr</option>
</select>

And:

  yourModelName: string;
  constructor() {
    this.yourModelName = 'hr';
  }
Coccus answered 13/10, 2017 at 19:13 Comment(3)
what is log(rate)? is that just an example of a custom function? Please note, I'm not binding to any variable in the component class and the select box is only there so that a user can choose a value so I can use that value in logic somewhere else in the template.Pubescent
No, it was just a row that I added for testing purpose and I forgot to delete. I copied and pasted it for mistakeCoccus
Anyways you need to bind a reference in the component in order to preselect a value. This is how ngModel worksCoccus
H
10

If you don't wish to have a two-way binding, you can set ngModel to the 'default' value and with the template local variable get the selected value:

<select #rate ngModel="hr">
    <option selected value="hr">hr</option>
    <option value="yr">yr</option>
</select>

<p *ngIf="rate.value == 'hr'">hr</p> 
<p *ngIf="rate.value == 'yr'">yr</p>

{{rate.value}}

DEMO

Hollis answered 13/10, 2017 at 21:57 Comment(3)
Thank You! I'd been reading through other ways of doing this and they just weren't working. The docs for Angular 5 pipes show it as [(ngModel)]='rate' which would work if I were populating the options dynamically and all of the stuff that comes with that. But for only two or three hard coded options this works. And it is so simpler conceptually. This is something so basic and simple I was surprised at the convoluted suggestions/fixes.Mcconaghy
Be careful, this is now deprecated with v7 if you are using reactive forms: angular.io/api/forms/FormControlName#use-with-ngmodelVermeil
@rynop, no, even with previous versions, it's better to not mix reactive forms and ngModel. But the OP doesn't use it anyway and my exemple either :)Hollis
S
0

In case you are using Reactive form, setting up default value while you define your form model could also help.

Sporades answered 19/8, 2022 at 6:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.