Get selected option in ngOptions with protractor - angularjs

How can I get the object associated to the selected option inside within a dropdown (select)?
Here's my html:
<select ng-model="selSeason" ng-options="season as season.name for season in seasons"></select>
Every season is an object with several properties and I'd need to get the object associated to the selected object (and not only its text or value).
I know ng-repeat has something like (to select name of the 5th season):
element(by.repeater('season in seasons').row(4).column('name'));
Is there something similar for by.options() selector?
Thanks

You can use by.options with evaluate():
var seasonNames = element.all(by.options('season in seasons')).evaluate("season.name");
seasonNames.then(function (values) {
console.log(values); // array of season names is printed
});
You can also filter out the selected option with filter():
var selectedSeasonName = element.all(by.options('season in seasons')).filter(function (option) {
return option.getAttribute("selected").then(function (selected) {
return selected;
});
}).first().evaluate("season.name");
selectedSeasonName.then(function (value) {
console.log(value); // selected season name is printed
});

What you are looking for is the custom by.selectedOption locator.
element(by.selectedOption('model_name'))
For a better description, read this: https://technpol.wordpress.com/2013/12/01/protractor-and-dropdowns-validation/

I ended up evaluating not the selected option but the ng-model associated to the select:
HTML
<select ng-model="selSeason" ng-options="season as season.name for season in seasons"></select>
JS
element(by.model('selSeason')).evaluate('selSeason').then(function(season){
console.log(season.name);
});

Your binding looks good, you can read all the properties easily by using your ng-model variable 'selSeason', see this example
<select ng-model="user"
ng-options="x as x.name for x in users track by x.id"
class="form-control"
ng-required="true">
<option value="">-- Choose User --</option>
</select>
var id = $scope.user.id;
var name = $scope.user.name;
var role = $scope.user.role
For more detail check this

Related

Angular - how to make a an option field (with ng-repeat) depend on previously chosen value in option field?

I have 3 fields.
1st - option field / ng-repeat over available dates
2nd - option field / based on the date chosen by user, I do ng-repeat over quantity. I have tried all different ways but I can't make it depend on the first option field or other things don't work. Any help would be great! Thanks !!
html:
<div class="containerDiv">
<div>
<select ng-model='date'>
<option ng-repeat="availableDateProduct in product " value='{{i}}'>{{availableDateProduct.dateOfActivity}}
</option>
</select>
</div>
<div ng-repeat="availableDateProduct in product ">
<select>
<option ng-repeat='i in quantityLister(availableDateProduct.quantity)' value='{{i}}'>
{{i}}
</option>
</select>
</div>
<div>
<button>Book</button>
</div>
</div>
js:
app.controller('ProductCtrl', function($scope, ProductsFactory, $stateParams) {
ProductsFactory.fetchByTitle($stateParams.title)
.then(function(product) {
$scope.product = product;
})
$scope.quantityLister = function(num) {
var array = [];
for (var i = 1; i <= num; i++) {
array.push(i)
}
return array;
}
})
data:
var products = [
{
title:'Bowling',
description:'Its fun!',
photoUrl:'https://www.1.jpg',
quantity:12,
price:9,
dateOfActivity: '2017-13-07'
},
...
]
Thanks!!
Angular has a directive built specifically to accomplish this task; ng-options.
First, we define an object in the controller that will hold the values selected from the dropdown:
$scope.reservation = {};
Next, we use ng-options on our dropdowns, and use the ng-model property to accept the value selected. In the first dropdown, we take the array of products, display the dateOfActivity for each product, and save the product object to ng-model when selected. (work from right to left in the ng-options definition).
ng-model="reservation.selectedProduct"
ng-options="product as product.dateOfActivity for product in products"
In our second dropdown, you have defined a function to take a number and spread it into an array. We call this function from reservation.selectedProduct.quantity, and then use this array as the basis for the ng-options:
ng-model="reservation.selectedQuantity"
ng-options="num for num in quantityLister(reservation.selectedProduct.quantity)"
Now we have an object which has the selected values for both dropdowns, we just need to change the quantity in the original array on button press. we also want to clear the selections afterwords, to ensure that the user can't accidentally make a duplicate reservation.
$scope.reserve = function (){
$scope.reservation.selectedProduct.quantity -= $scope.reservation.selectedQuantity;
$scope.reservation = {};
};
Here we use the shorthand -= to subtract the selectedQuantity from the selectedProduct.quantity. since selectedProduct is two way bound, the change to selectedProduct is reflected in the original object in the product array as well. However, The quantityLister function isn't dynamic; if we don't reset $scope.reservation, the second dropdown would hold a now invalid number of available reservations.

How to set initial value for select element in AngularJS?

I write dependent comboboxes and faced such problem - how to set initial value? For example, I have a form for adding new records:
Controller.js:
...
$http({
url: '/api/address/fill',
method: 'POST'
}).success(function (data) {
$scope.itemsForLevelOne = data
}).error(function(errorData) {
...
});
$scope.updateOne = function() {
$http({
url: '/api/address/change',
method: "POST",
data: {'tobId' : $scope.itemOne.id}
}).success(function (data) {
$scope.itemsForLevelTwo = data;
}).error(function(errorData) {
...
});
};
...
View.html:
...
<label>Level One</label>
<select class="form-control m-b"
data-role="listview"
data-inset="true"
ng-options="someValue as someValue.tobName for someValue in itemsForLevelOne"
ng-model="itemOne"
x-ng-change="updateOne(itemOne)">
</select>
<label>Level Two</label>
<select class="form-control m-b"
data-role="listview"
data-inset="true"
ng-options="someValue as someValue.tobName for someValue in itemsForLevelTwo"
ng-model="itemTwo"
x-ng-change="updateTwo(itemTwo)">
</select>
...
From the controller I can make call to the server- side (Play Framework in my case) and then extract data from the database and save them.
In the forms of editing and deleting records I should to set the initial values for all select elements.
How can I do it?
AngularJS uses bidirectional binding. The selected option is stored in the ng-model attribute when a selection is made, and it's also read from the ng-model attribute on order to display the correct selection.
So you pick the element to select from the array of options, and initialize the variable corresponding to the ng-model of the select. For example, to have the first element selected, you do
$scope.itemOne = $scope.itemsForLevelOne[0];
You should use ng-repeat instead of ng-options
<select>
<option ng-repeat="someValue as someValue.tobName for someValue in itemsForLevelTwo" ng-selected="expression_to_be_evaluated"
</select>
ng-repeat with the option tag, gives you more control than ng-options.
What JB said, but remember it is IMPERATIVE that the values match between the object that you pass to the ng-model and the list values themselves; In your case:
$scope.itemOne = someValue;
$scope.itemTwo = someValue2;
someValue and someValue2 NEED to match up with a corresponding option value, or else you will end up with the dreaded empty first box.
Another solution would to add a default chooser option which instructs the user to choose an option:
...
<label>Level One</label>
<select class="form-control m-b"
data-role="listview"
data-inset="true"
ng-options="someValue as someValue.tobName for someValue in itemsForLevelOne"
ng-model="itemOne"
x-ng-change="updateOne(itemOne)">
<option>Please Select An Item</option>
</select>
...
This way, the person filling out the form will never select an option involuntarily. This default option, because it has no value, will disappear when a selection is made.

Angular: pre-select from Rest-ful Service

I´d like to pre-select a select-field from a given Restful-Service:
$scope.findOne = function () {
$scope.teams = Teams.query();
$scope.teamCategory = TeamCategories.get({
teamCategoryId: $stateParams.teamCategoryId
});
};
This is my function to get one Team-Category from my database.
<select name="assignedTeams" size="10" id="assignedTeams" multiple class="form-control" data-ng-model="teamCategory.assignedTeams" ng-options="team._id as team.detailName for team in teams" required>
<option value="">Please choose.</option>
</select>
and this is my select-Field. Both Services return the correct results, I can see them in the console. But the select-Field is not pre-selected. Where is my fault?
You need to make $scope.teamCategory.assignedTeams be an array that only contains the team ids you want to select. It should look like the following:
$scope.teamCategory.assignedTeams = [1,2,3];
The values 1, 2, 3 should be the teams ids you want selected.
I got it to work. The Restful-Service should not populate the response - then the selectFields are correctly set.
Thanks to your help!

Angularjs select with additional option

I have a multiple select that is connectted to the model. I would like to add an additional option that's not part of the model and handle the click event. Is that possible and how?
Language:
<select multiple name="Language_Custom"
ng-model="model.Language_Custom"
ng-required="true"
ng-options="pn.Value as pn.Label for pn in Language_Custom_PossibleValues">
</select>
Create a function that returns a copy of your Language_Custom_PossibleValues array and appends your additional option to it. This lets you add an option without changing the underlying model.
$scope.getLanguages = function(){
var languages = [];
angular.forEach($scope.Language_Custom_PossibleValues, function(item){
languages.push(item);
});
languages.push({Value: 0, Label: 'Extra Option'});
return languages;
}
Now use that function as the source in the ng-options:
Language:<select multiple name="Language_Custom"
ng-model="model.Language_Custom"
ng-required="true"
ng-options="pn.Value as pn.Label for pn in getLanguages()"
ng-change="changeLanguage()"></select>
You also need a changeLanguage function that is called when the selected item in the list changes:
$scope.changeLanguage = function(){
if($scope.model.Language_Custom.indexOf(0) > -1)
alert('do somthing here');
}
Plunker
Here is the solution I used:
<div>
Language:<select multiple name="Language_Custom" ng-model="model.Language_Custom" ng-required="true">
<option ng-click="selectAllMultiValues(model, 'Language_Custom', Language_Custom_PossibleValues)">Select All</option>
<option ng-repeat="pn in Language_Custom_PossibleValues" ng-model="p.Value">{{pn.Label}}</option>
</select>
</div>

angularjs : select with different (key, value) not working properly

I am trying to load angular "select" with the following code
<select class="span11" ng-model="user.countryOfResidence" ng-options="c.option as c.value for c in countries" required>
Its loads the data into the select but the default selected value is empty.
my countries array is
$scope.countries = [{option:'TL', value:'TIMOR-LESTE'},
{option:'TK', value:'TOKELAU'},
{option:'TJ', value:'TAJIKISTAN'},
{option:'TH', value:'THAILAND'},
{option:'TG', value:'TOGO'},];
if i change 'TL' to 'TIMOR-LESTE', (same string for "option" and "value") it works fine. Can any one kindly tell me what is the problem with my code.
user object is
$scope.user = {
countryOfResidence : $scope.countries[0].value
};
A select populated with ng-options will set the ng-model field to what is specified as the value, not the option
In the example you've given, you're setting user.countryOfResidence to countries[0].value, which in this case is 'TIMOR-LESTE', but the value key is 'TL', so it won't select it by default.
For better readability, I always like to structure my select options with 'label' and 'value' keys, like so:
// Controller
$scope.countries = [
{value:'TL', label:'TIMOR-LESTE'},
{value:'TK', label:'TOKELAU'},
{value:'TJ', label:'TAJIKISTAN'},
{value:'TH', label:'THAILAND'},
{value:'TG', label:'TOGO'}
];
$scope.user = {
countryOfResidence: $scope.countries[0].value
};
};
// View
<select class="span11" ng-model="user.countryOfResidence" ng-options="c.value as c.label for c in countries" required=""></select>

Resources