Selected value for angular select not be set on page refresh - javascript

The selected value of my angularjs select is not being set on page refresh.
It is set if I navigate to a different view and then navigate back again.
The model for the select is saved to local storage and is initialized into the scope onload.
I have checked that the data in the scope is the same in the two situations of navigating away and back again, and refreshing the page. The data is exactly the same.
After a lot of investigation, I see that when the select is pristine, or when the page is refreshed, the select list will have an extra blank option, like first one below with value ?:
<select ng-model="question.answer" class="form-control" ng-options="opt as opt.value for opt in question.options" >
<option value="?" selected="selected"></option>
<option value="0">1</option>
<option value="1">2</option>
</select>
Note The above HTML is the output. My Angular view just has:
<select ng-model="question.answer" class="form-control" ng-options="opt as opt.value for opt in question.options" />
I'm not sure why this would be preventing the correct option from being selected as the correct object is still present at question.answer. See a simplified version of the model below:
var question = {
options: [
{
id: 1,
value: "1"
},
{
id: 2,
value: "2"
}
],
answer: {
id: 2,
value: "2"
}
};
My understanding is that in ng-options, the first opt specifies that this is the value that should be assigned to the variable specified in ng-model. In other words, I will be assigning an object in the options array to question.answer, rather than just the value. I can see by looking at the model that this is the case.
But I'm not sure how Angular will use the value in question.model to determine which option is set as selected.
I wonder if the problem is something to do with the fact that the values of the options are set as indices of question.options and it can't work out from question.answer which index that answer is.
So, I guess my questions are:
- Why is the correct option not being set when this extra <option value="?" selected="selected"></option> is present?
- How does Angular determine how to use the model to set the selected option (aka - what are those funny indices in the option values?)
Sorry this post is so long. Thank for reading.
Update:
Using the Chrome AngularJS Batarang extension, that the value being set to question.answer for a picklist is e.g.:
{
$ref: $["options"][1]
}
which will means the value of the picklist is "2".
So that is how it is using the indices of the options are being used, but is that how I have to set my model? i.e. using the $ref etc?

I edited the answer after I looked at what you were doing.
The ng-options attribute has a track by expression to do just what you're talking about:
ng-options="opt as opt.Value for opt in question.options track by opt.id"
See the updated fiddle: http://jsfiddle.net/CkLEu/6/

Related

How do I set the default option for select with AngularJS?

I have been working on trying to set the default pre-selected option for angularJS and for some reason I can't. Here is a link to the relevant Plunkr.
Here is the relevant code:
<select
ng-model="selectedOption"
ng-options="option.value as option.name for option in options">
</select>
I've tried ng-init and a bunch of different ways; I can't figure how to make the top option the preselected one.
The linked answer suggests using ng-init. I would go with assigning default option into selectedOption in controller or directive's link function:
$scope.selectedOption = options[0]
I don't see a need to use another directive for this simple task.
If what you want is to set one of the options pre-defined in options,
in your ng-init do something like this $scope.selectedOption = <value> where <value> is the value property of the object you want to be marked as selected by default. For example 1 if your first object in options would be, {value: 1, name: "Option Number 1}. See code below:
$scope.options = [{value:1, name: "Option 1"}, {value:2, name: "Options 2"}];
$scope.selectedOption = 1;
On the other hand, if you only want to show a predefined option indicating the user to select one option (and not one of the options in your options)...
This is a very simple (but effective way to achieve that). See code below:
<select
ng-model="selectedOption"
ng-options="option.value as option.name for option in options">
<option value="">--Default--</option>
</select>
just update model of the element i.e. selectedOption='yourDefaultValue'
What is the version of angular are you using?
if the latest one, then you can use below code::
<select
ng-model="selectedOption" [ng-value]='yourDefaultValue'`
ng-options="option.value as option.name for option in options">
</select>
Link to updated plunkr : http://plnkr.co/edit/SkS0NqyXpnMcddu80anf?p=preview
Updating model code moved in the function and also select as and track by should be avoided as mentioned in the angular doc
Be careful when using select as and track by in the same expression.

Want to add none as value in select multiple

I am using chosen.jquery.js for select field
<select chosen multiple data-placeholder="Select Body Part(s)"
ng-options="option.Name as option.Name for option in BodyPartList" ng-model="Body_Part">
<option value="" disabled>Select Body Part(s)</option>
</select>
But It shows only data-placeholder value in case of no data in model.
I want to show "Select Body Part(s)" as a option in list.
And user must not select this. Reason is that, I want to add dynamic "Unknown" value in list of Body_Parts. But it not reflect in list.
Same work for select having single selection.
I'm not seeing any problems with your code, as such. Like, I'm trying it and getting the visual behaviour I think you're wanting? Am I missing something?
Html just yours with ng-app etc, javascript is:
var myApp = angular.module('myApp', ['localytics.directives']);
myApp.controller('MyController', function($scope) {
$scope.BodyPartList = [
{ Name: "Arm" },
{ Name: "Leg" }
];
$scope.Body_Part = [];
});
Not sure if data-placeholder is actually doing anything.
Fiddle: http://jsfiddle.net/7187f6d9/
That said, it's not "working". In the fiddle I put a regular select box alongside the chosen one, and the chosen one doesn't seem to be writing to the ng-model correctly. I'm not sure what's up with that.
You can choose the below option
https://harvesthq.github.io/chosen/#optgroup-support
or push another item to the top of the array from server side as your custom label and disable it on client side with the help of ng-if and $index properties of ng-repeat and angularjs. If this make sense then its fine else i can give you a demo.
I hope your query is, you want show a place holder as current selected value but user shouldn't be able to select it.
Instead of making it disabled, make ithidden. Then display an error if a user doesn't select any other options, using the value of placeholder option.
A sample snippet is added below. If value of select is Error, write a case to throw a error back to user.
<select>
<option value="Error" hidden>Select any Company</option>
<option value="Toyota">Toyota</option>
<option value="Nissan">Nissan</option>
<option value="BMW">BMW</option>
</select>
Hope this helps! If not, ping me with your query. :)

ng-model with association on select box with ng-repeat on options

I have a Plunker here illustrating my issue. I have an object with an associated division. There is no division_id on the object, but in order to set or update the division I need to set the division_id field. Here's the sample object:
$scope.user = {
name: "John",
age: 32,
division: {
id: 3,
name: "Alpha"
}
};
And the example divisions:
$scope.divisions = [
{
name: "Gamma",
id: 1
},
{
name: "Alpha",
id: 3
},
{
name: "Beta",
id: 5
}
];
The way I'm building the select box is with ng-repeat, which I was hoping would bypass the need to track ng-model for the selected value.
<div class="form-group">
<label for="">Division</label>
<select type="text" ng-model="user.division_id">
<option ng-repeat="division in divisions"
ng-selected="user.division.id == division.id">{{ division.name }}</option>
</select>
</div>
As you can see in the demo, the selected attribute is being placed on the right option, but still the select box display is blank. Even if I add division_id: 3 to the object, it continues to be blank. How can I get this to work without having to do a conversion on the object when loading and updating?
Edit: To address this question being flagged as a duplicate, I think this is unique because I'm asking how to build the select box with ng-repeat, not ng-options. Though the answer is similar to the answer for the proposed duplicate, I think other people might get stuck on this method and find it helpful to see the answer requires a different technique.
If you update your select as follows it will display by default to the users division.id.
<select ng-model="user.division" ng-options="d as d.name for d in divisions track by d.id">
You seemed to be wanting to have a separate model division_id, the only reason I can think of for this is that you wanted to control the persistence of the user model when the selection is updated. If for some reason you want to intercept the end-users selection to the user model (or even just the in-memory user object) being updated then use a copy/there are many ways to do that, but it's not clear if that's what you're asking.
Updated plunkr
Note it would have worked to have kept the same option ng-repeat syntax, but this is the recommended angular way to deal with options.
As per your plunker, you need to remove the ng-model directive from the select tag for it to work.
if you need to set a division_id variable for your code, you can use ng-init.
<div class="form-group">
<label for="">Division</label>
<select type="text">
<option ng-repeat="division in divisions"
ng-selected="user.division.id == division.id"
ng-init="division_id=division.name">{{ division.name }}
</option>
</select>
</div>

AngularJS 1.4: Select List Value not Initializing Correctly when List is Inserted with $compile

Here's some quick background info. I just upgraded to Angular 1.4. I'm using an API written in C# for my server-side calls.
A section of my page shows 2 select lists (Project & Sub-project). Both are supposed to default to "(Select a ______)", which I list as the first option of each select with "value" of 0. The appropriate ng-model variables are initialized to 0.
The actual HTML code for the select lists is being generated on the server side using string concatenation, passed to the client via $http, and inserted using a directive that calls $compile (not ideal at all, but my client has pretty much chained me to this API). Prior to the 1.4 update, everything was working nicely.
Now, my Project select list is defaulting to nothing. When I inspect the element, this is what I see...
<select ng-change="updateSubProjList()" ng-model="curProjID">
<option value="? number:0 ?"></option>
<option value="0">(Select a Project)</option>
<option value="1">First Project</option>
<option value="2">Second Project</option>
...
</select>
...with that first "? number:0 ?" entry being the one that is currently selected. My Sub-project select list still initializes just fine, which makes this even more odd.
I know that there were some updates to $compile in the update to AngularJS 1.4, but I can't figure out a solution to my problem. Any assistance would be greatly appreciated.
There seems to be a change in 1.4 related to how the selected option is matched against ngModel by comparing the value attribute in <option value="0"> - it now requires to explicitly use a string to match, rather than allowing for an integer.
In fact, the documentation clearly states:
The value of a select directive used without ngOptions is always a string. When the model needs to be bound to a non-string value, you must either explicitly convert it using a directive ... or use ngOptions to specify the set of options.
To fix, change the initialized value of $scope.curProjID to be a string:
$scope.curProjID = "0"; // instead of $scope.curProjID = 0;
When there is no match (and there isn't, unless you assign a string "0"), select adds an "unknown" option: <option value="? number:0 ?"></option>.
There is another way: using a directive implementing a parser and a formatter. See http://plnkr.co/edit/JZPay8jgm5AXKGXDCjSb
thankx goes to narretz!
Pseudo code:
<select convert-number ng-model="x">
<option value="100">100</option>
<option value="200">200</option>
</select>
app.directive('convertNumber', function() {
return {
require: 'ngModel',
link: function(scope, el, attr, ctrl) {
ctrl.$parsers.push(function(value) {
return parseInt(value, 10);
});
ctrl.$formatters.push(function(value) {
return value.toString();
});
}
}
});
I had the same issue. Instead of making sure that my JavaScript code uses string all over the place, I did the following:
Removed the <option ...> items from the HTML file
Introduced a list into JavaScript, similar to:
var orderQuantities = [
{ id: 100, text: '100' },
{ id: 200, text: '200' },
{ id: 300, text: '300' },
];
Did make sure that orderQuantities is visible in the scope
Used ng-option in the select tag as follow:
<select ng-model="vm.entity.OrderQuantity" ng-options="orderQuantity.id as orderQuantity.text for orderQuantity in vm.orderQuantities"></select>
<select ng-model="x">
<option value="100">100</option>
<option value="200">200</option>
</select>
scope.x = '200'
or read this doc.
https://docs.angularjs.org/guide/migration

Angular blank option selected

I'm banging my head against the wall on this one.
I have an array of objects that will be used to populate a select drop down:
CardCount = [{"ClientId": "0010", "Description": "0010 (206 Members)"}, {"ClientId": "0051", "Description": "0051 (1 Member)"}, ........]
When I attempt to use ng-options, the value of the option is set to the index, not to the ClientId as desired. To get the value in each option to be the ClientId, I have to use a ng-repeat in the options. Here is my html:
<select ng-model="CurrentClient">
<option ng-repeat="item in CardCount" value="{{item.ClientId}}">{{item.Description}}</option>
</select>
Initially, all is well, the select and options are generated correctly, and the first option is correct. Now, when a certain button is clicked somewhere else on the page, it becomes necessary to recreate this select and options with a smaller array of similar objects. However, doing so creates a blank option with a value of "? string:0010 ?". This is the option that is selected. Again, I cannot use ng-options to correct this problem because doing so doesn't set the value attribute in the option tags correctly. So, I added this to the option tag:
<option ng-repeat="item in CardCount" value="{{item.ClientId}}" ng-selected="CurrentClient == item.ClientId">{{item.Description}}</option>
Now, that does mark the correct option as selected. However, the drop down still shows the blank option. Here's the rendered html:
<select ng-model="CurrentClient">
<option value="? string:0010 ?"></option>
<option value="0010" selected="selected">0010 (206 Members)</option>
</select>
As you can see, it sets the correct option to selected. However, it sets it to selected="selected", and not just selected. When I inspect element and change selected="selected" to selected (remove the equals and everything after it), the drop down then correctly displays the correctly selected option.
Again, initially the select and options work great. The problem seems to happen only after the array that the select is created with is changed. How can I get this select and options working correctly after I change the array, and not show that first blank option?
Thanks!
Changed you option element to set value by default.
<option ng-repeat="item in CardCount track by item.ClientId"
value="{{item.ClientId}}">{{item.Description}}</option>
Hope this could help you. Thanks.
ng-options is definitely the way to go:
<select ng-model="selected.ClientId" ng-options="it.ClientId as it.Description for it in clientList">
<option value="">-</option>
</select>

Categories

Resources