Roll back ngOptions select to unselected state - angularjs

ngOpions creates a blank option like option html below if the model value doesn't match any of the option values:
<option value="?" selected="selected"></option>
After a selection is made, AngularJS removes this first empty option html from the select html.
I have a use case where I want to roll back the state of the html select to the unselected option which AngularJS removed. I tried ngModel methods like $setPristine(), $rollbackViewValue(), and $setUntouched(). But none of these mothods puts the state of the select back to the initial state with the empty option.
Is it possible to truely roll back an AngularJS select element to have the empty option after a selection is made?

The code for ngOptions (line 473 in ngOptions.js ) suggests that only single-select can get it, and that the writeValue function (called when the ngModel changes) has to be invoked with a null value (not undefined, as === is used.)
So you can try setting your model variable to null.
If that doesn't work, I expect you may be out of luck as far as proper solutions go, and might need to re-render the whole directive. You can create a pretty simple directive to do that, similar to what's suggested in this answer: https://stackoverflow.com/a/22133080/624590

Related

Set selected attribute for single/multi selection with ng-options

It seems that angular's behavior with respected to the selected attribute has changed back and forth with each major version. So I'm just looking for someone to tell me if this is achievable in the 1.5.x release using ng-options rather than ng-repeat.
What I'm trying to do:
Have angular create html like the following(so that it can be interpreted by a jquery plugin)
<select multiple="multiple"...>
<option value="abc123" label="Justin" selected="selected">Justin</option>
</select>
I've tried many variations of this
<select ms-multi-listbox multiple="multiple" class="multi-select"
id="ym" name="ym" ng-model="groupCtrl.memSelection"
ng-options="mem as mem.displayName for mem in groupCtrl.selectableMembers track by mem.id">
with no luck.
the model looks like this:
groupCtrl.memSelection =["abc123"];//inbound from api as is selectableMembers
Here is a plunk I've been playing with (try changing the angular version for added confusion): Plunker
Any ideas are welcome.. I mainly wanted to avoid ng-repeat because it has a lot of overhead in longer lists but obviously slow is better than not working so I'll use it until I learn how to do this with ng-options.
Thanks!
edit:
Here is a ng-repeat that achieves the result I want:
<option ng-repeat="mem in groupCtrl.selectableMembers" value="{{mem.id}}" label="{{mem.displayName}}" ng-selected="groupCtrl.memSelection.indexOf(mem.id)>=0">{{mem.displayName}}</option>
enter code here
Be careful when using select as and track by in the same expression. AngularJS API ngOptions
Your expression for ng-options can't work. Using select as and track by in the same expression evaluates mem.id to mem.id.id. Change the expression to
ng-options="mem as mem.displayName for mem in groupCtrl.selectableMembers track by mem.id"
And how you set the selected objects don't look right to me as well. You can not just set the id, you have to set the whole object as selected otherwise your ng-options expression evaluation will also fail. Therefore change your selection to (assuming selectable data is stored in $scope.model as it is in the plunk example).
$scope.memSelection = [$scope.model[0], $scope.model[1]]
I have updated the plunk and it works for single and multi selection.
For more information read AngularJS API ngOptions.

Angular ngOptions 'track by' and null value validation issue

I have a select list using ngOptions and the 'track by' feature like this:
<select validdate="{{date}}" ng-model="code" ng-options="code.description for code in codelist track by code.value">
<option value=""></option>
</select>
The code object has various properties, including a start and enddate which determines the validity of the code. There is a seperate 'date' property which is used to check if the code can be selected or not. For this validdate-directive I need the whole object, therefore I use the track by and cannot use the 'as' to fill the ng-model property.
This works properly, except for the initial null value.
When the validation returns false (and marks the select-box accordingly) and the user then selects the null value, the validation doesn't get reset.
The validator isn't called, even though the ng-model property 'code' changes from an object to a null-value. It seems that because of the track by, it does not trigger the validation directive. Does anyone know a solution for this?
It was a bug in my particular version of Angular, 1.3.8. Upgrading solved it, but for reference this JS Fiddle shows the bug (and changeing the version there solves the bug) http://jsfiddle.net/2tvy2jgh/1/
enter code here

Dynamic Select List Default Selected Item - Angular JS

I have the code listed below which works fine, however when i attempt to add ng-model and related ng-change to the select, an empty option is added. I understanding why, it is because on init the selectedOption for ng-model is empty.
What I want to do is set a default value so when I can use ng-change to set options IsSelected value to true when user selects it. I'm just not sure how to go about this, I have no issues doing this when I'm working with a static generated select list, but for some reason I can't figure it out for this dynamic generated list.
Any input is appreciated!
<div ng-repeat="optionType in productDetailModel.OptionTypes">
<select name="{{optionType.OptionTypeName}}">
<option ng-repeat="option in optionType.Options"
value="{{option.OptionValue}}">{{option.OptionValue}}
</option>
</select>
</div>
Here's plunkr I mocked to give a basic idea of what I have in mind: http://plnkr.co/edit/xBDfc0XzDwsF0mBiFZOv?p=preview
The initial option is blank because the model is initially undefined.
As tymeJV said, initializing your scope inside of your .js will define a default value that will be shown as selected initially.
$scope.modelName = $scope.optionType.Options[0];
It might be helpful to use ng-options instead of ng-repeat. One reason why it might be beneficial is that ng-options does not create a child scope (unlike ng-repeat). This could help simplify linking to your model and avoid confusion.
<select name="{{optionType.OptionTypeName}}" ng-model="modelName" ng-options="option for option in optionType.Options">
</select>
This article covers the basics of ng-options as well as discusses why it would be used as opposed to ng-repeat.
Hope this helps.
Use ng-options when using a select!
<select name="{{optionType.OptionTypeName}}" ng-model="someModel" ng-options="option as option for option in optionType.Options>
</select>
And then set the ngModel to the default option you want selected:
$scope.someModel = $scope.optionType.Options[0]
There is one directive of select element is ng-init but it call once while first time rendering, but if you change the options dynamically then it will not call again. So for that you need to set the model field with value in scope just below of your new option population logic.
$scope.modelName = $scope.Options[0]; // if array
$scope.modelName = $scope.Options[key]; // if Json Object

Can't get Angular select to update with selected value

I'm using selects to allow a user to switch between events and years. Each change will pull appropriate data from the server, return and update the page. However, the select box goes from the selected value to an empty value. I've looked at numerous solutions and they aren't working.
<select
ng-model="eventName"
ng-options="item.value for item in eventOptions track by item.value"
ng-change="changeEvent(eventName.value)">
</select>
This is the changeEvent function:
$scope.changeEvent = function(eventName){
$scope.eventName = eventName; //wrongly assumed this would update the selected value
$scope.getData($scope.eventName,$scope.eventYear); //this returns the json - correct
$scope.updateSelected(); //meant to update the select field value on the page - fails
};
$scope.eventName or $scope.eventYear values will properly update on a change, but has no effect on the page. The selects just empty of a selected value.
UPDATED (with corrected code)
I wanted to post the changes I made more clearly than the comment allows.
I removed the object param "value" from the options and the argument from the function call (eventName.value).
<select
ng-model="eventName"
ng-options="item for item in eventOptions track by item"
ng-change="changeEvent()">
</select>
And the changeEvent function gets simplified to:
$scope.changeEvent = function(){
$scope.getData($scope.eventName,$scope.eventYear);
};
It all works as expected! Thanks to all, especially Delta who got me looking at it the right way.
So, your event name variable is set to be item. not item.value so instead of passing in changeEvent(eventName.value) try passing in changeEvent(eventName). either way the value you are passing into your method doesnt match the value of your model's variable
item.value for item in eventOptions track by item.value
so for this statement, you are saying make my options ng-model=item but make their value=item.value so they show what you want them to show but still have all the information you need from each one.
Upon further inspection is looks like you dont need:
$scope.eventName = eventName;
$scope.updateSelected();
Angular should be updating your eventName for you, you just need to call the change method.
I'm not sure you need:
ng-change="changeEvent(eventName.value)"
if you use ng-options the model will be updated in the scope automatically on selection. You could watch the value in the controller if you want to do other stuff when it changes:
$scope.$watch('eventName', function() {
//do stuff
});

populate a select with ng-grid columns

I've got an ng-grid that I want to be able to search on particular columns. The user enters some text and chooses a column from a dropdown. My UX guy doesn't much fancy the search-field-in-every-column-header that ng-grid supports.
Here is my Plunker:
http://plnkr.co/edit/WofBDA6QQkCDcwDMznzf?p=preview
(I haven't bothered with the text field yet, just worried about the field picker so far)
I've got a method that grabs the field and displayName for each field and populates my select with options, but for some reason, it gives me an empty first option. I don't want an empty one - and certainly not if it's going to look like this:
<option value="? undefined:undefined ?"></option>
I want it to default to a field of my choice (in the plunker example, I want it to default to 'age')
I can't figure out why I'm getting an undefined option - unless it's because the control is being rendered by my getFilterFields() function BEFORE the colDefs are fully defined. I've tried various ways of delaying the getFilterFields()function - I played with init: gridInit parameter, but so far, no joy.
How can I assure that
1] my dropdown contains ONLY valid columns, and
2] one of them is preselected?
It's better to use ng-options and set the model to the option that you want to be selected.
<select ng-model="selectedItem"
ng-options="item.value as item.name for item in filterOptions.filterFields">
</select>
and in the controller, set:
$scope.selectedItem = "age"; // equal to the value of the default option

Resources