Initial ng-model value not set in select - angularjs

I have an enum (I code using TypeScript):
export enum AddressType
{
NotSet = 0,
Home = 1,
Work = 2,
Headquarters = 3,
Custom = -1,
}
Then in my controller I have a field named type, into which I set the initial value that should be selected in the select input (I set it to AddressType.Headquarters).
Finally, in my HTML I put the following:
<select ng-model="Ctrl.type" ng-options="addressType for addressType in Ctrl.getAddressTypes()"></select>
Everything seems to work fine except one thing: for some reason Angular does not select "3" (Headquarters) initially in the select after all bindings have been updated. Angular creates an extra option like this instead:
<option value="?" selected="selected"></option>
So for some reason Angular cannot figure the initial option to select in the combo.
If the user selects another option of the combo box, Ctrl.type is updated properly so the binding works fine for that part. Basically my problem is just that the option that should be selected initially is not selected as expected.
What am I missing here that is causing that problem?

Found the problem:
The array returned by Ctrl.getAddressTypes() was an array of strings:
["0", "1", "2", "3", "1"]
and what was stored in Ctrl.type was of type number.
AngularJS compares the array supplied to ng-options to the value supplied to ng-model using the '===' operator. 3 does not equal to "3" in that case - that's why it did not work.

I often run into this when using number id's. My way around this quirk is to add ''+ to convert it to string type:
<select ng-options="''+u.id as u.name for u in users"

In a function if the below code is added and the same is called from the ng-init then the issue is also getting resolved. This will resolve the string comparison issue.
$scope.Ctrl.type = "" + $scope.Ctrl.type + "";

I happens because you didn't initiated selected value. Try to set init value with ng-init:
<select ng-model="Ctrl.type"
ng-options="addressType for addressType in Ctrl.getAddressTypes()"
ng-init="Ctrl.type = ..."
></select>
See this Demo Fiddle where we have 2 combos with and without init value. You can see that one combo HTML seems like:
<select ng-model="selectedItem1"
ng-options="selectedItem1.name as selectedItem1.name for selectedItem1 in values" class="ng-pristine ng-valid">
<option value="?" selected="selected"></option>
<option value="0">General</option>
<option value="1">Super</option>
<option value="2">Trial</option>
</select>
The proper one:
<select ng-model="selectedItem"
ng-options="selectedItem.name as selectedItem.name for selectedItem in values"
ng-init="selectedItem = values[1].name" class="ng-pristine ng-valid">
<option value="0">General</option>
<option value="1" selected="selected">Super</option>
<option value="2">Trial</option>
</select>

Related

AngularJs - Dependent Select - How to get the picked value

so I have two dependent select, one for states and the other for cities. It works fine but I can't get the value picked in the first select. I tried everything, the only result I got was the list of all the cities. What I need is which state picked.
My code:
<label>States</label>
<select id="provincia" class="form-control" ng-model="ciudades" ng-options="provincia for (provincia, ciudades) in provincias">
<option value=''>Elegir</option>
</select>
<label>Cities</label>
<select id="ciudad" class="form-control" ng-disabled="!ciudades" ng-model="modelciudad" ng-options="ciudad for ciudad in ciudades" required>
<option value=''>Elegir</option>
</select>
My list is something like this:
$scope.provincias = {Florida:['Miami', 'Orlando']}
I try using ng-model on Option tag but with no result.
Thanks

Set default value of select to null option

According to the Angular documentation, you can create a null option that is not part of your model. This allows you to have a descriptive option. I.E. in their example they have -- choose color --. How can I make the null option the default option? I want the user to see this descriptive null option when they first load the page.
Bonus points if you can also tell me how to make the null option be disabled via angular.
The value is set to null automatically.
But if you receive data from REST for exaple and it will be set to some value - you can add ng-init to your select tag.
And for disable null option after selection of some value - you need to add ng-disabled to your option tag.
<select ng-model="model" ng-options="item for item in items" ng-init="model = null">
<option value="" ng-disabled="!!model">--Select option--</option>
</select>
And in controller:
.controller('MainCtrl', function($scope) {
$scope.model = 'First';
$scope.items = ['First', 'Second', 'Third'];
});
Demo: http://plnkr.co/edit/esoX26I9bESE59yneOvv
Just use the ng-if to completely remove it once they have a selection. Best option from my experience.
<select name="objectSelector"
ng-model="selectedObject"
ng-options="obj for obj in Objects" required>
<option value="" ng-if="!selectedObject">--- Select Object ---</option>
</select>
If you really, really must show the '--- Select Object ---' after a choice has already been made, then you may just want to insert a second
<option value="" ng-if="!!selectedObject" disabled>--- Select Object ---</option>
Then the visible option will display accordingly...haven't found a simple way to set 'disabled' dynamically.

Angular dropdown default value not working

In my angular application , I have created one dropdown containing sim name. Those names are coming from API. I also set default value as All sim. But it is not working. Here is my code snippet.
<select ng-model="selectSim" class="selectpicker" ng-options=" item.description for item in simList">
<option value="all">Select All</option>
When I I render this page , I can see dropdown containing Sim name but my "select all" option is missing.
I cant figure it out whats wrong in my code.
Set option value = ""
<select ng-model="selectSim" class="selectpicker" ng-options=" item.description for item in simList">
<option value="">Select All</option>
</select>
A single hard-coded element, with the value set to an empty string, can be nested into the element. This element will then represent the null or "not selected" option.
try this
This is html code (don't need option tag )
<select ng-model="selectSim" class="selectpicker" ng-options=" item.description for item in simList">
and write this way in your controller code where assign values to simList
$scope.simList.push({ description : "Select All", Id: 0 }); // this line helps to dynamoically add defualt value in `$scope.simList` array, now the default item added in bottom side
$scope.selectSim= $scope.simList[$scope.simList.length - 1];// this is helps to assign default item `selectSim` model
'*' here Id: 0 is your value name and dummy values. you need to change value name

Angular adds strange options into select element when setting model value

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?
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>
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.
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.
I was running into this same problem earlier this evening, where I saw a select option showing up as the first in my list even though I didn't explicitly create it. I was filling a list of select options in my controller and using the same ng-options syntax mentioned above by jessedvrs (except that I was also inserting the "select an option" default option in the controller rather than marking it in the HTML like he was).
For some reason the select list would always show an additional option at index zero with a value of "?", but when I changed how I filled my default option in the controller, this issue went away. I was populating the select options by making an API call, filling them inside of a promise. I made the mistake of also populating my default "select an option" option as the first thing I did in that promise, but when I did this instead outside of the promise (prior to making the API call), the select options populated the way I waned them to.
I think jessedvrs option is one solution to the problem (setting the default option in the HTML markup), but if you prefer to populate your options in javascript instead, I would suggest to still set the default option prior to making any calls to an API or processes that may still be running while the HTML is being rendered.
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()" >
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"
While pushing data on scope variable we can use following code
$scope.enquiryLocationRow.push({'location': EnqLocation.location, 'state_id': Number(EnqLocation.state_id), 'country_id': Number(EnqLocation.country_id)});
it resolved my issue
vm.kanoonCourses is object array, vm.courses is string array :
<table class="table table-hover">
<tr style="font-weight: bold; background-color: #dfedf8;">
<td>index</td>
<td>course in our system</td>
<td>course in outside system</td>
</tr>
<tr ng-repeat="course in vm.courses">
<td style="vertical-align: middle;">{{$index+1|persianNumber}}</td>
<td style="vertical-align: middle;">{{course.CourseTitle}}</td>
<td>
<select
ng-model="course.KanoonCourseTitle"
ng-options="option as option for option in vm.kanoonCourses">
</select>
</td>
</tr>
</table>

Angularjs ngOption with array

I want to add an html select with options AM,PM with angularjs,
what i need is having the key and the value of the option be the same :
<option value="AM">AM</option>
<option value="PM">PM</option>
My html looks like this
<select ng-model="ampm" ng-options="k as v for (k , v) in ampms"></select>
and my controller looks like
$scope.ampm = (new Date().getHours()) >= 12 ? 'PM' : 'AM';
$scope.ampms ={"AM":"AM","PM":"PM"};
and every thing working fine.
My question is why i cant have the same thing when i used an array (i tried all the options in the ng-options)
as this
$scope.ampms =["AM","PM"];
what ever i do i always get this
<option value="0">AM</option>
<option value="1">PM</option>
What i want is using an array like above with the option has the key and the value the same.
With AngularJS, you don't need to worry about what the value of the option is. All the selects I've seen with ng-options have values of 0 through whatever. If you're just looking for a dropdown with the two options, it can be as simple as
<select ng-model="ampm" ng-options="currOption for currOption in ['AM', 'PM']"></select>
See http://jsfiddle.net/EyBVN/1/
This is is a default behavior of ng-options in Angular. If you do not specify a key name, angular will automatically choose to use the index rather than a key. The code that does that can be seen on line 405 in /src/ng/directives/select.js on Angular's Github repository.
It can't even be forced by "value as value for (index, value) in values".
But as dnc253 just beat me to the punch with his answer (it showed up while I was typing)... you don't have to worry about it, Angular does it all for you automatically.
I did find a way to place specific data in the value of the options for a select. You have to add an ng-repeat attribute to the option tag inside the select tag:
<select id="{{question.id}}" name="{{question.id}}"
class="{{question.inputclass}}" ng-required="question.required"
title="{{question.title}}">
<option value=""></option>
<optgroup ng-repeat="group in question.data" label="{{group.group}}">
<option ng-repeat="item in group.data" value="{{item.value}}"
ng-selected="{{item.value == question.defaultValue}}">
{{item.description}}
</option>
</optgroup>
</select>
As a bonus, I left the option group tags in place to serve as an example for everyone.
The question.data JSON is:
[
{"group":"Canada","data":[{"value":"Ontario","description":"Toronto"},
{"value":"Quebec","description":"Quebec City"},
{"value":"Manitoba","description":"Winnipeg"}
]
},
{"group":"Mexico","data":[{"value":"Jalisco","description":"Guadalajara"},
{"value":"Nayarit","description":"Tepic"}
]
},
{"group":"United States of America","data":[
{"value":"Alabama","description":"Montgomery"},
{"value":"Georgia","description":"Atlanta"},
{"value":"Mississippi","description":"Jackson"},
{"value":"Louisiana","description":"Baton Rouge"},
{"value":"Texas","description":"Ausint"}
]
}
]

Resources