ng-option track by group name breaks the select - angularjs

I have a dropdown select with grouped ng-options. The user should be able to dynamically change the naming of the group name in an input field. On change of the group name value the select directive is not being updated unless you make a new selection.
I fixed this with using track by group name, but now the select dropdown is broken. Note that the option you select is not the one that is actually selected.
Is there a way to have both dynamically updated group name and a working select?
<select ng-options="player.name group by player.team for player in players track by player.team" ng-model="systemType.tertiaryEquipment"></select>
Here's the jsfiddle : http://jsfiddle.net/07woeam8/2/

You have several options here, but there are trade-offs that you need to consider.
First, the thing that is messing up your selections is the track by expression, which shouldn't be player.team because you are not selecting teams. It should be either player.name or nothing at all. Keep in mind that tracking by player.name will make the groups in the select object to not be updated in real-time.
Second, if you want the groups in the option menu to change dynamically, you need to change the entire $scope.players object, and not just change a string value inside of it. For example, you can use angular.copy:
$scope.change = function() {
var copy = angular.copy($scope.players);
copy[0].team = 'betsdfhsk';
$scope.players = copy;
};
This presents the other trade-off you need to consider. Changing the object reference completely will also void your selected object if you didn't use track by player.name in the first option.
But here's a working fiddle.

Related

Setting label with ng-options and 'as' ('track by' alternative)

I need all of my drop down menu options to have a label that matches their displayed value. Currently the code I use to create the options is ng-options="country.Code as country.Country for country in countries". I know the preferred way to do this is with track by, but since I already use as, my code breaks when I do so. How can I work around this?
You can use track by in NgOption when using as but it's important to set the complete country object (not country.Code) to the NgModel or else the track by statement will fail.
Try it like this
ng-options="country as country.Country for country in countries track by country.Code"

Globally Set All Select Boxes to First Available option in AngularJS

I have a lot of select boxes in my application, being generated by lists of data and assigned to various ng-models.
I want to set the ng-model value to the first available option (respecting filters) of all select inputs globally in the app.
So for example a select input like this:
<select ng-model="entry.employee">
<option ng-value="employee.name" ng-repeat="employee in employees | filter:active">{{employee.name}}</option>
</select>
The entry.employee ng-model defaults to null, I need every select box to never be null but always select the first valid option of a select input by default.
It needs to be global as well and be generic enough to work with any type of select input.
Here is the data:
$scope.employees= [
{'name':'Bill'},
{'name':'Frank'},
{'name':'Ted'},
];
Instead of using ng-repeat on option elements use directly ng-option on select tag.
for example
<select class="form-control" ng-options="item.name for item in employees track by item.id" ng-model="selectedItem"></select>
in you controller use:
$scope.selectedItem=$scope.employees[0];
your object would be like:
$scope.employees= [
{id:'1','name':'Bill'},
{id:'2','name':'Frank'},
{id:'3','name':'Ted'},
];
In this case let you select tags be 'n' numbers but whenever you want you ng-model to be the first one just initialize it with the first element in your Object.
Also there is a good thing using ng-option is whenever you want to change the value of the select element at runtime you just need to update the selectedItem element.
Hope this resolves your query

Default Value for Select with ng-options

jsFiddle: http://jsfiddle.net/shandylion/2r3z1uma/
I need to display a list of objects as a list of dropdowns, where changing a dropdown changes the corresponding element in the list. Ideally, each dropdown should default to that element.
So, with the following data:
$scope.allPeople = [{"name":"Ann", "Age":10},
{"name":"Barb", "Age":20},
{"name":"Carl", "Age":30}];
$scope.selectedPeople = [{"name":"Ann", "Age":10},
{"name":"Carl", "Age":30}];
and the following HTML:
<div ng-repeat="selectedPerson in selectedPeople">
<select ng-options="person as person.name for person in allPeople"
ng-model="selectedPeople[$index]"
name="select-{{$index}}" id="select-{{$index}}"></select>
</div>
there should be two dropdowns, with the first defaulting to "Ann" and the second to "Carl".
I've tried using ng-selected, but that only seems to work with <option> tags, not inside a <select>. Other Stack Overflow posts suggest we should always use ng-options and never an <option> with an ng-repeat, so I'm stuck as to how to get this to default to the appropriate value.
Here's a sample plunker, which has a working solution as well as the faulty one described below.
The pitfall with dropdowns is that when you want to preselect a value from a list of options, the selected model should be a reference pointing to the same object from the bound list. Say you have:
var list = [{ id: 1, value: 'first'}];
var model = { id: 1, value: 'first' };
<select ng-options="item.value for item in list" ng-model="model"></select>
This will not preselect the dropdown, because list[0] and model are not the same object, although they look alike. If you set ng-model to list[0] it should be preselected just fine.
Since you're using person.name for person in allPeople, the selected option returns person.name as value. You're presetting your $scope.selectedPeople array's values as objects, which does not match with what your select list will return, and hence your initial values are not set properly.
If you want to have person.name as the value of each option, you should change your $scope.selectedPeople to this:
$scope.selectedPeople = ["Ann", "Carl"];
On the other hand if you want to return person as the value of each option, change your ng-options expression to person as person.name for person in allPeople, which means you return person and show it as person.name for each person in $scope.allPeople.

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