Angulars: ng-options linked - angularjs

I have this data:
{
"resources":{
"animals":[
{
"id":"1",
"value":"dog",
"names":[
{
"id":"1",
"value":"Carl"
},
{
"id":"2",
"value":"July"
}
]
},
{
"id":"2",
"value":"cat",
"names":[
{
"id":"1",
"value":"Peter"
},
{
"id":"2",
"value":"Frank"
}
]
},
]
}
}
I want a user select: first an animal and then select a name (filtering animal id).
Getting the ids in the result.
I thought this example:
<select ng-model="select.id_1" ng-options="a.id as a.value for a in resources.animals">
<option value="">-- choose animal --</option>
</select>
<select ng-model="select.id_2" ng-options="...">
<option value="">-- choose name --</option>
</select>
For example(Selection Cat and Frank):
select =
{
id_1: '2',
id_2: '2'
}
I don't know what code put in the second ng-options.
In this example there are two levels, how it would be with n levels?

ngOptions doesn't support multi-dimensional arrays.
Try this:
<select ng-model="select.id_1" ng-options="a.id as a.value for a in resources.animals" ng-change="firstChange()">
<option value="">-- choose animal --</option>
</select>
<select ng-model="select.id_2" ng-options="...">
<option value="">-- choose name --</option>
</select>
In JS,
$scope.firstChange = function(){
$scope.Subarray = [];
for(i=0; i<$scope.resources.animals.length; i++){
if(select.id_1 == $scope.resources.animals[i].id){
$scope.Subarray = $scope.resources.animals[i].names;
break;
}
}
}
Use the $scope.Subarray in the second ng options.
Here's a similar question, maybe try this too.

Related

Trying to display value in my select option

When I try to display my value the select box is always empty. The value is a integer 0 1 2 3 . In this case it should show 0, but the box is empty. What am I doing wrong?
vmDialog.dataModel.requestType value is equal to a 0 integer, but not displaying.
<select class="form-control " name="requestType" ng-model="vmDialog.dataModel.requestType">
<option value=0>0</option>
<option value="{{0}}">0</option>
<option value="0">0</option>
</select>
Firstly there is a simple HTML issue, you need to ensure that each option has a unique value, so far you have used the value 0 for all the options, so when the requestType has a value of 0, the UI cannot pick which of the items should be selected.
If the value supposed to be one of 0,1,2,3 then you need to make sure that there is an option with a corresponding value that can be selected.
What you probably want to do is bind the options to an array that is in the view model:
// on vmDialog
var requestTypeOptions = [
{ name = 'Zero', value = 0 },
{ name = 'One', value = 1 },
{ name = 'Two', value = 2 },
{ name = 'Three', value = 3 },
];
Then in the view: (using ng-options)
<select class="form-control"
name="requestType"
ng-model="vmDialog.dataModel.requestType"
ng-options="o.value as o.name for o in vmDialog.requestTypeOptions track by o.value | orderby: 'value'"
class="form-control input-sm">
</select>
A good write-up for ng-options here: https://stackoverflow.com/a/30507651/1690217
You could also use ng-repeat if you need to customise the template:
<select class="form-control " name="requestType" ng-model="vmDialog.dataModel.requestType">
<md-option ng-value="o.value" ng-repeat="oin vmDialog.requestTypeOptions | orderBy: 'value'">{{o.name}}</md-option>
</select>

Angular select populate dropdown?

This is my JSON data:
[{
"table":"mCity",
"drpdownItems":[
{
"Display":"ab",
"Value":1
},
{
"Display":"a",
"Value":10
},
{
"Display":"Delhi",
"Value":7
},
{
"Display":"Devgad",
"Value":4
},
{
"Display":"Kalyan",
"Value":5
},
{
"Display":"Mumbai",
"Value":2
},
{
"Display":"Nashik",
"Value":9
},
{
"Display":"New Mumbais",
"Value":6
},
{
"Display":"Panji ",
"Value":8
},
{
"Display":"Pune",
"Value":3
}
]
}]
I want the following output:
<select>
<option value="1">ab</option>
<option value="10">a</option>
<option value="7">Delhi</option>
</select>
I tried following:
ng-options="City.Display as City.Value for drpdownItems in CmbsData.table['mCity']"
ng-options="City.Display as City.Value for drpdownItems in CmbsData[0].drpdownItems"
Cmbs is an array, and drpdownItems is a property of the object which is the first element of that array
Edit based on comment: generalized form
ng-options="City.Display as City.Value for drpdownItems in (CmbsData | filter:{table:'mCity'}).drpdownItems"
Update based on comment below:
<select
ng-options="City.Value as City.Display for City in (CmbsData | filter:{table:'mCity'}:true|limitTo:1)[0].drpdownItems"
ng-model="selectedCity">
</select>
In order to make a strict match, please use true in your filter. It is better to uselimitTo:1because there may be multiple matches.filterandlimitToalways result in an array. Since we are limiting by 1, we can use[0]` index to get the city we want.
Original answer:
You need to use like this
<select name="" id="" ng-options="City.Value as City.Display for City in CmbsData[0].drpdownItems" ng-model="selectedCity"></select>
The syntax of ng-options is _select_ (as _label_)? for (_key_,)?_value_ in _collection_

setting first item as selected for hash type

Using angularjs while creating a select element, I can set the first value as selected using
ng-init="item.state = stateArray[0]"
How to set the first item selected for key/value type array?
var States = { "AL": "Alabama", "AK": "Alaska", "AZ": "Arizona" }
html code:
<select ng-model="item.state" ng-options="k as v for (k,v) in States" class="form-control"></select>
I also tried
ng-init="item.state = Object.keys(States)[0]"
For ng-options:
Demo: http://jsfiddle.net/U3pVM/17821/
HTML:
<select ng-init="o = getFirst();" ng-model="o" ng-options="k as v for (k,v) in States" class="form-control"></select>
JS:
$scope.States = {
"AL": "Alabama",
"AK": "Alaska",
"AZ": "Arizona"
};
$scope.getFirst = function () {
var v = Object.keys($scope.States)[0];
return v;
};
For ng-repeat:
You can use $first for selecting the first option in case of ng-repeat.
ng-selected="$first?'selected':''"
try this
ng-init="item.state= stateArray['AL']"
Try this way.
In your controller,
$scope.States = { "AL": "Alabama", "AK": "Alaska", "AZ": "Arizona" };
var arrProp = Object.getOwnPropertyNames($scope.States);
$scope.item = {};
$scope.item.state = arrProp[0];
And HTML as it is,
<select ng-model="item.state" ng-options="k as v for (k,v) in States" class="form-control">
<option value="">Select </option>
</select>

select(name).option(value) selects wrong option?

I've a got a strange issue. When I try to select a date the select() function selects the wrong option.
Ng-Model:
days = ['01', '02', '03', '04', ..., '31'];
Markup:
<select ng-model="day" id="day" name="day" ng-options="day for day in days">
<option value="" disabled="disabled"></option>
</select>
e2e test:
it('should select correct date', function () {
select('day').option('30');
expect(element('#day option:selected').text()).toEqual('30');
});
So my question is: Why does select('day').option('30') select the 31th day when select('day').option('02') works as expected?
So I was wondering what value it's targeting as it's working fine in other places.
The documentation is very sparse so either it's a feature or a bug :)
What I think is going on is the select() tries to select the value in some sort of order. I.E. it first tries to select the option by value then it tries to select it by model value, or something along those lines.
So I looked up the implementation of the select function.
From github:
/**
* Usage:
* select(name).option('value') select one option
* select(name).options('value1', 'value2', ...) select options from a multi select
*/
angular.scenario.dsl('select', function() {
var chain = {};
chain.option = function(value) {
return this.addFutureAction("select '" + this.name + "' option '" + value + "'",
function($window, $document, done) {
var select = $document.elements('select[ng\\:model="$1"]', this.name);
var option = select.find('option[value="' + value + '"]');
if (option.length) {
select.val(value);
} else {
option = select.find('option').filter(function(){
return _jQuery(this).text() === value;
});
if (!option.length) {
option = select.find('option:contains("' + value + '")');
}
if (option.length) {
select.val(option.val());
} else {
return done("option '" + value + "' not found");
}
}
select.trigger('change');
done();
});
};
return function(name) {
this.name = name;
return chain;
};
});
So the "problem" is that select tries to select from the values in the DOM element, that is the <option value="THIS VALUE"> then it tries to find the value by what's being displayed <option>THIS VALUE</option> and then it tries to do a contains on the value. It doesn't actually use the model value at any point.
So select('day').option('02') worked because it was matching the displayed text, where as select('day').option('30') was matching the option value which has an offset.
Keep in mind the generated HTML is:
<select ng-model="day" id="day" name="day" ng-options="day for day in days">
<option value="" disabled="disabled"></option>
<option value="0">01</option> <-- note it starts at 0 not 1
<option value="1">02</option> <-- select('day').option('02') matches display text '02' as no value 02 exists.
<option value="2">03</option>
<option value="29">30</option>
<option value="30">31</option> <-- select('day').option('30') matches value 30 before display text 30 with value 29.
</select>
To "solve" this issue a new function needs to be created (or alter the existing).
angular.scenario.dsl('selectModel', function() {
var chain = {};
chain.option = function(value) {
return this.addFutureAction("select '" + this.name + "' option '" + value + "'",
function($window, $document, done) {
var $ = $window.$; // jQuery inside the iframe
var select = $document.elements('select[ng\\:model="$1"]', this.name);
var option = select.find('option').filter(function(){
return $(this).text() === value;
});
if (!option.length) {
option = select.find('option:contains("' + value + '")');
}
if (option.length) {
select.val(option.val());
} else {
return done("option '" + value + "' not found");
}
select.trigger('change');
done();
});
};
return function(name) {
this.name = name;
return chain;
};
});
This does the trick.
The Angular created option tags have indices as value, when the source model is a list:
$scope.listItems = [
"day 1",
"day 2",
"day 3",
"day 4",
"day 5"
];
and
<select ng-model="listItem" ng-options="item for item in listItems"></select>
create the following HTML:
<select ng-options="item for item in listItems" ng-model="listItem"
class="ng-pristine ng-valid">
<option value="?" selected="selected"></option>
<option value="0">day 1</option>
<option value="1">day 2</option>
<option value="2">day 3</option>
<option value="3">day 4</option>
<option value="4">day 5</option>
</select>
While the option tags have keys as value, when the source model is a map:
$scope.objItems = {
"day 1":"1",
"day 2":"2",
"day 3":"3",
"day 4":"4",
"day 5":"5"
};
and
<select ng-model="objItem2" ng-options="value as key for (key, value)
in objItems"></select>
create:
<select ng-options="value as key for (key, value) in objItems"
ng-model="objItem2" class="ng-valid ng-dirty">
<option value="day 1" selected="selected">day 1</option>
<option value="day 2">day 2</option>
<option value="day 3">day 3</option>
<option value="day 4">day 4</option>
<option value="day 5">day 5</option>
</select>
However this never poses a problem because when the user selects an option, Angular looks up at the indexed position inside the source and assigns that value to the model.
I am not quite familiar with e2e testing but I think the reason you are getting a different value everytime you select an option is that you are trying to access the value stored in the option tag and not what Angular has stored in the model for you.
Fiddle

How do I set a selected option for select in Angular

I have an object
$scope.colleges = [{"CollegeCode":"40","CollegeName":"College1"},
{"CollegeCode":"35","CollegeName":"College2"},
{"CollegeCode":"32","CollegeName":"College3"},
{"CollegeCode":"15","CollegeName":"College4"}]
I'm populating a select element with it's contents
<select ng-model="collegeSelection" ng-options="c as c.CollegeName for c in colleges" name="selectCollege"></select>
It renders on the page like so
<select class="ng-pristine ng-valid" name="selectCollege" ng-options="c as c.CollegeName for c in colleges" ng-model="collegeSelection" style="" selected="selected">
<option value="?" selected="selected"></option>
<option value="0">College1</option>
<option value="1">College2</option>
<option value="2">College3</option>
<option value="3">College4</option>
etc....
I'm also binding this select to collegeSelection and when an item is selected the object look like this
$scope.collegeSelection = {"CollegeCode":"32","CollegeName":"College"}
When someone clicks edit on the page, the college I want selected by default comes from the userToUpdate object.
$scope.userToUpdate = {
Id: 1,
FirstName: 'John',
LastName: 'Doe',
CollegeCode: '35,
CollegeName: 'College2',
Active: true
};
When an edit button and the userToUpdate object is populated, I would like the college in the select element to be set to the college in the user object. How could one make this happen? FYI, the value in the rendered select does not match the CollegeCode. It seems angular uses the index from the colleges object. Thanks
Try this one
<select ng-model="collegeSelection" ng-options="c.CollegeCode as c.CollegeName for c in colleges" name="selectCollege"></select>
<span>{{collegeSelection}}</span>
<input type="button" ng-click="switch()" name="switch" value="switch" />
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function ($scope, $filter) {
$scope.colleges = [{ "CollegeCode": "40", "CollegeName": "College1" },
{ "CollegeCode": "35", "CollegeName": "College2" },
{ "CollegeCode": "32", "CollegeName": "College3" },
{ "CollegeCode": "15", "CollegeName": "College4" }
]
$scope.switch = function () {
$scope.collegeSelection = "32";
};
});

Resources