AngularJs's ng-options - clarification? - javascript

I have this small demo.
Basically , it's a select element with this data :
address: {
select: {
code: "0",
name: "Select proof of address"
},
letter: {
code: "1",
name: "Letter"
},
photograph: {
code: "2",
name: "Photograph"
}
}
And here is the select
<select ng-model="current.addressCode" ng-options="value.code as value.name for (key,value) in student.address"</select>
Questions:
Question #1 - Looking at the Ng doc -
And so , I try to compare
value.code as value.name for (key,value) in student.address
to the second line ( which i find most appropriate)
select as label for (key , value) in object
What is going on here ?
value.code goes to select ???
Html select element has an option tag with value and inside text like :
<option value="volvo">Volvo</option> thats' all.
What did they mean in their docs ?
Question #2
How can I bind this object of myne to a regular sane value,text select ?
(I want the code to be the value and the name to be as text)
Currently I dont see any value in the dom :

You are correct in understanding that example two fits your needs, that is:
select as label for (key , value) in object
Here, as the documentation mentions:
select: The result of this expression will be bound to the model of the
parent <select> element. If not specified, select expression will
default to value.
So, for your use case, your existing code for the select tag is correctly structured:
<select ng-model="current.addressCode" ng-options="value.code as value.name for
(key,value) in student.address"></select>
value.code value is stored in current.addressCode while, in the select dropdown, you should see value.name as the options label.
EDIT: So, to answer your questions:
Question 1
In this case, "select" is just a variable name - a placeholder if you may like for the documentation to explain about it (which it does further below). In your code, the value of the variable that is used instead of select is the one that gets bound to the select's ng-model (In your case, value.code)
Question 2
Exactly as you have mentioned:
<select ng-model="current.addressCode" ng-options="value.code as value.name for
(key,value) in student.address"></select>
This will give you the necessary value, text select tag automatically. When you select an option, the value.code associated with that option gets stored in current.addressCode

http://jsfiddle.net/7FL76/1/
how about this:
it requires simple change :
address: [
{
code: "0",
name: "Select proof of address"
},
{
code: "1",
name: "Letter"
},
{
code: "2",
name: "Photograph"
}
]
the reason is your Key is same as nested Name ( like, letter - Letter ) , so json is a bit redundant.
as result you will see.
value as a code, and text as a name .

Related

Initializing select value in nested ng-repeat

I'm having trouble properly initializing the select boxes in a form, built with nested ng-repeats. I have parent table rows built with an ng-repeat, and a select box whose value is bound to an attribute in the parent row. The values in the select box are pulled from a nested child array, constituting available selections for the row.
<tr ng-repeat="asv in asvs">
<td>{{asv.scenario_asv_id}}</td>
<td>{{asv.asv_target_id}}</td>
<td><select ng-model="asv.asv_target_id">
<option ng-repeat="version in asv.asv_targets"
value="{{version.asv_target_id}}"
ng-selected="asv.asv_target_id == version.asv_target_id">
ID: {{version.asv_target_id}} - Name: {{version.asv_target_desc}}
</option>
</select>
</td>
</tr>
In my Plunker, you'll see that the first 2 selects initialize properly, yet the 3rd does not. Can someone advise how to implement this properly?
https://plnkr.co/edit/NGcEMNSHCDAYK8UBOKYl
It is recommended that you use ng-options with select elements. Please replace your select code with the example below:
<select convert-to-number
ng-options="version.asv_target_id as ('ID: ' + version.asv_target_id + ' - Name: ' + version.asv_target_desc) for version in asv.asv_targets track by version.asv_target_id"
ng-model="asv.asv_target_id">
</select>
Because your value is numeric you will have to add the following directive as per https://code.angularjs.org/1.4.7/docs/api/ng/directive/select
module.directive('convertToNumber', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(val) {
return val != null ? parseInt(val, 10) : null;
});
ngModel.$formatters.push(function(val) {
return val != null ? '' + val : null;
});
}
};
});
The problem happening here is during the creation of select options using ng-repeat
{
"scenario_asv_asv_target_id": "16150-CI101592-3475",
"scenario_asv_id": 16150,
"appl_ci_id": "CI101592",
"asv_target_id": 3475,
"asv_target_desc": "Default General Purpose",
}
If you move your data which are going to match your criteria to the end of the json, your value will get selected.
Because in the loop the select option is getting created,so it resets the already created ng-select values.
For example, I have moved the option which are going to be by default to the end of json set and the value is getting selected.
This is not recommended, for understandging.
Check into the plunker:
https://plnkr.co/edit/G83l6OdIfr5vlNgMSeR7?p=preview
I haven't edited your code, i have just replaced your data set.
So,
you should use ng-options as follows
<tr ng-repeat="asv in asvs">
<td>{{asv.scenario_asv_id}}</td>
<td>{{asv.asv_target_id}}</td>
<td>
<select ng-model="asv.asv_target_id"
ng-options="version.asv_target_id as version.asv_target_desc for version in asv.asv_targets"
ng-selected="true">
</select>
</td>
</tr>
final code
https://plnkr.co/edit/w8nOENAiL72SX68L7LVv?p=preview
disclaimer:
I have concentrate on explaining and helping you to select default option, so don't expect me to prettify the option data by appending data and desc in it. Do it on your own.

Ng-init in the selection for default value with AngularJS doesn't work

In web app I have a list of Expenses, which that if you press above it takes you to a new page to edit the selected Expense. When the user click on an element of list, I save the Object (the selected Expense) in a Global Object common in whole application and I retrieve it when I am in the Editing controller:
$scope.companySelected = GlobalApplicationData.selectedExpenseList;
The GlobalApplicationData.selectedExpenseList is an Object:
$$hashKey: "object:39"
_id: "33aa5549-7802-40d9-bc89-8780705b8c9b"
_rev: "3-eb940cb990524112723f711618e0cf51"
ad_table_id: 1000596
company_name: "Company 1"
data: Object
recordid: 1000005
__proto__: Object
In one expense there is only one company.
So, in this page of editing I have some field (input type text, date, etc). And I also have a selection with the list of the Companies of the logged user. To retrieve that list, I made this function:
$scope.getCompanyList = function() {
EditExpenseListSrv.getCompanyListDetail(user).then(function (companyListDetail) {
$scope.companyList = companyListDetail;
$scope.$apply();
}).catch(function (err) {
console.log(err);
});
};
CompanyListDetail is an array of Obejct:
companyListDetail: Array[5]
0: Object
1: Object
2: Object
3: Object
4: Object
And this is one example of those object:
_id: "44e620dc-e715-453f-882b-3f21aeef48fe"
_rev: "1-c09c9f3350e853e588f3358aaafc0374"
ad_table_id: 1000146
data: {
description: "text"
id_company: 513424
name: "Company 2"
}
recordid: 1000002
So the company of the selected Expense ($scope.companySelected) will definitely part of the list obtained by the query ($scope.companyList). But I want to give the user the possibility to change it.
So I would like to make a selection containing the list ($scope.companyList) and default already selected the Company corresponding to $scope.companySelected.
I've writter this, but it doesnt work:
<select class="selection" ng-model="companySelected"
ng-init="companySelected = globalApplicationData.selectedExpenseList"
ng-options="company
as company.data.name for company in companyList">
But it doesn't work. I can see in the selection all the Companies, but don't select the default value
When you are assigning a default value to the select, you need to assign the object, so it won't work, when assigned with the same data of some other object:
Note:
a) data is the array which is getting looped in the select list
b) selectedcountry is the model which is bind on select list.
Option 1:
Using ng-init:
<select ng-model="selectedcountry" ng-init="selectedcountry = data[0]" ng-options="item.name for item in data">
<option value="">Select</option>
</select>
Demo 1.
Option 2:
Assigning the default from the controller
$scope.selectedcountry = $scope.data[0];
Demo 2
You can try to do the initialisation in the controller:
$scope.companySelected = "the value that you want to set here"
Or you can try to put the ng-init inside the parent of the select. Once I had a problem like this and I solved it putting the ng-init in the parent tag. Example:
<div id="parent" ng-init="companySelected = globalApplicationData.selectedExpenseList">
<select ...>
</div>
Another idea would be to put companySelected inside an object. I have had some problems (I am not sure why) with the forms if I was using $scope.value inside the ng-value instead of using $scope.formData.value

check the value with ng-options value

I created the normal select box using ng-options. I have the value property and members array in the object
$scope.currentprop = {
name : "graphFillDirection",
members : [{
name : "ttb",
caption : "Top to Bottom",
}, {
name : "btt",
caption : "Bottom to Top"
}, {
name : "ltr",
caption : "Left to Right"
},{
name : "rtl",
caption : "Right to Left"
}],
value : "ttb"
}
so i created the dropdown values with members.name.and this is my html
<select ng-model="currentprop.value" ng-options="value.name for (key , value) in currentprop.members"></select>
Question
i iterate through members array and i check name with value property. so if members.name is equal to value then i should pass the checked index value to ng-model.
In normal javascript we used to like this currentprop.members.name.indexOf(currentprop.value). so this is what i need to assign to ng-model.
currently i using currentprop.value in ng-model. In this place i should use index value of checked value.
i dont know how to achieve it. please help me. Thanks in advance. Plnkr here
Try ng-selected
<select ng-model="currentprop.value"
ng-options="value.name as value.name for (key,value) in currentprop.members"
ng-selected="{{currentprop.value == value.name}}">
</select>
Working Plunker
If I understand your issue correctly, the problem is with ng-options. I think what you are looking for is this:
ng-options="member.name as member.caption for member in currentprop.members"
<select ng-model="value" ng-options="value.name as value.name for (key,value) in currentprop.members" ng-change=chk(value)></select>
To compare when your select an value
$scope.chk=function(data)
{
console.log(data== $scope.currentprop.value)
}
Try this:
http://plnkr.co/edit/R9zFHhXxTFqHGPgN0n4K
I made some small changes and added an ng-change element that will check whether the selected value equals your defined value.
<select ng-model="currentprop.selected" ng-change="onDropdownChange()" ng-options="value.name as value.name for (key , value) in currentprop.members">
<option value="">Choose one...</option>
</select>
$scope.onDropdownChange = function(){
if ($scope.currentprop.selected === $scope.currentprop.value){
alert("Selected === value");
}
}

angularjs - remove option from input select

Can't figure this out for the life of me. Using AngularJS.
I have a dropdown Select field with several options. It is a part of a form that may be completed multiple times (ie "add another" type form). Now, one of the options may only be used once. How can I remove this option from all other select fields after it has been used?
What I'm working with:
html
<select ng-model="item.itemtype">
<option ng-repeat="i in itemtype" value="{{i}}" ng-init="item.itemtype = itemtype[0]">{{i}}</option>
</select>
angularjs
$scope.Items = [
{ 'itemtype': '', 'desc': '', 'color': '' }
];
$scope.itemtype = [
'shirt',
'pants',
'hats',
'shoes',
'special'];
What I've tried (and really doesn't work)
$scope.specialremove = function() {
var exist = Items.indexOf("special")
if (exist !== 0) {
return '';
}
else {
return 'special';
}
}
I'm hoping I don't have to turn to any other framework to solve this. Feel free to point out any other problems/errors/inefficiencies in my code.
The first thing that can help is using ng-options:
ng-options="type for type in itemType".
It would be better to have objects with label and value properties, in order to write it as
ng-options="type.value as type.label for type in itemType"
and separate the displayed label from the actual value of the selection.
In your controller you should have something like:
$scope.itemType= [
...
];
$scope.selectedItem= $scope.itemType[0];
So that you can write the select as:
<select ng-Model="selectedItem" ng-options="item.value as item.label for item in itemType"></select>
To remove a selected item you can watch the value of selectedItem in the controller: when it matches the value you want, remove it from the array and update selectedItem accordingly.
Here is a basic fiddle. I simply remove the third option after selecting it, and reset the selected item to the first.

AngularJS : get select label without modifying ng-model

I'm currently stuck with a problem which seems simple :
Controller :
$scope.fruits = [{
name: 'AP',
label: 'Apple'
}, {
name: 'BA',
label: 'Bananas'
}];
HTML code :
<select
ng-model="meal.fruit"
ng-options="fruit.name as fruit.label for fruit in fruits">
</select>
<p>Fruit : {{meal.fruit}}</p>
Problem is, this displays
Fruit : BA
Instead of
Fruit : Bananas
I can't modify ng-option to "fruit as fruit.label" because I need my model "meal.fruit" to be "AP" or "BA" (because it is a java enum deserialize by Jackson, and it requires the Enum value).
JSFiddle
In summary, I need meal.fruit to be "BA" and I also want to be able to display the selected value "Bananas" somewhere else.
What can I do ?
EDIT :
The solution that worked for me was found by Maxim Shoustin, (many thanks !) :
I modified my code to have the following :
http://jsfiddle.net/2qfSB/77/
And then I modified my submit method to add the following :
$scope.meal.fruit = $scope.meal.fruit.name;
Just change ng-options:
ng-options="fruit.label as fruit.label for fruit in fruits">
Fixed Demo: Fiddle
as a side note
You can set by default 1st element to avoid empty combo by using ng-init:
<select
ng-model="meal.fruit"
ng-options="fruit.label as fruit.label for fruit in fruits"
ng-init="meal.fruit = fruits[0].label"
>
Demo: Fiddle

Categories

Resources