Angular adds strange options into select element when setting model value
Solution 1
Angular does not set the value of a select element to the actual values of your array and does some internal things to manage the scope binding. See Mark Rajcok's first comment at this link:
https://docs.angularjs.org/api/ng/directive/select#overview
When the the user selects one of the options, Angular uses the index (or key) to lookup the value in array (or object) -- that looked-up value is what the model is set to. (So, the model is not set to the value you see in the HTML! This causes a lot of confusion.)
I'm not entirely sure using an ng-repeat
is the best option.
Solution 2
Using the following syntax with ng-options
solved this problem for me:
<select name="country_id" id="country_id" required="required" ng-model="newAddressForm.country_id" ng-options="country.id as country.name for country in countries">
<option value="">Select Country</option>
</select>
Solution 3
If your values are integers you should use "" even if they're not strings, that simple reason is exactly why you're getting an option with a question mark as a value.
You shouldn't be using this:
{ value: 0, name: "Pendiente" },
{ value: 1, name: "Em andamento" },
{ value: 2, name: "Erro" },
{ value: 3, name: "Enviar email" },
{ value: 4, name: "Enviado" }
This is the right way:
{ value: "0", name: "Pendiente" },
{ value: "1", name: "Em andamento" },
{ value: "2", name: "Erro" },
{ value: "3", name: "Enviar email" },
{ value: "4", name: "Enviado" }
If you've at least one record which isn't using "" you'll be getting this ? option value.
Solution 4
use " track by 'value' " at the end of your ng-options :D
like the example below:
ng-options="country.id as country.name for country in countries track by country.id"
Solution 5
When you assign a value to some select element, AngularJS looks for the provided value in the value attribute of the option tags in that select element. But the catch is, AngularJS does a type based comparison. So if the values in the option tags are strings (which usually is the case) and the variable you bind using ng-model is a number, AngularJS fails to find the matching option element and hence, creates its own element like this -
<option value="? integer:10 ?"></option>
The solution is, while binding itself, convert it to the appropriate type.
In this case, the solution would be to bind an Integer
<select name="country_id" id="country_id" required="required" ng-model="parseInt(newAddressForm.country_id)">
<option value="">Select Country</option>
<option ng-repeat="country in countries" value="{{country.id}}">{{country.name}}</option>
</select>
If the values are set as Strings, the trick would be to use
<select ... ng-model="newAddressForm.country_id.toString()" >
Related videos on Youtube
Comments
-
Swader about 4 years
I have a select element defined as such:
<select name="country_id" id="country_id" required="required" ng-model="newAddressForm.country_id"> <option value="">Select Country</option> <option ng-repeat="country in countries" value="{{country.id}}">{{country.name}}</option> </select>
All works fine when I'm not setting any kind of value in the directive which contains this select element. But when I do something like
newAddressForm.country_id = 98
, instead of selecting the option with value 98, Angular injects a new one at the top of the select element, like so:<option value="? string:98 ?"></option>
What gives? What sort of format is this and why does this happen? Note that if I do a
console.log(newAddressForm.country_id)
in the directive, I get a normal"98"
, it's just weird in the generated HTML.Edit: Situation update. Switched to using
ng-select
, but the issue persists.The weird element no longer appears, BUT, now there's another element at the top, one that has only a question mark
?
as the value, and no label.That's, from what I gathered, Angular's
"none selected"
option. I still don't understand why it won't select the option I tell it to select, though.Doing
newAddressForm.country_id = 98
still gives no results. Why is that?-
bryan over 7 yearsWere you able to find out the issue?
-
Swader over 7 yearsI gave up on Angular and have been living a happy life ever since
-
-
rGil about 11 yearsThis is different from, say, a radio group right? And if so, I wonder WHY the difference.
-
lucuma about 11 yearsIn general when using angular you shouldn't be concerning yourself with the values of html elements. It is the scope data that contains the appropriate values that you'd be manipulating/using.
-
frapontillo about 11 yearsYou really should be using
ng-select
as pointed out by @lucuma. -
Swader about 11 yearsTurns out ng-select works even if the values don't match the real values at all, but are just array indexes. However, it still won't auto-select an option element if I do newAddressForm.country_id = 98. It still inserts its own weird element onto the top of the options stack, only now it's just a single question mark as the value, and no label. Why won't it select the option I set?
-
Pelang almost 9 yearsI have the same issue with the question above. I tried using the ng-options as suggested. And I notice that the option values are the index of the array, not the object field value. I have this code ng-options="client.id as client.value for client in clients". and also got the option with the ? value.
-
Fan Jin over 5 yearsIndeed, best answer.