select in ng-option does not update - angularjs

I have the list of data that is coming from backend and I want to update the select value in the view which is not happening for some reason.
I tried ng-selected that does not works efficiently, sometime the model is update spmetimes not.
here is my code, can someone help?
<div class="listitem" ng-repeat="d in data">
{{d.name}}:
<select
ng-model="d.option"
ng-options="d.name for d in options"></select>
</div>
Controller
var myApp = angular.module('myApp', []);
myApp.controller("SomeController", function($scope) {
$scope.options = [{
"id": "id1",
"name": "p1"
}, {
"id": "id2",
"name": "p2"
}];
$scope.data = [{
"name": "data1",
"option": {
"id": "id1",
"name": "p1"
}
}];
});
http://jsfiddle.net/gFCzV/58/

You need to use select as label group by group for value in array track by trackexpr, Read DOCs
ng-options="option.name for option in options track by option.id"
DEMO, However note this will not work in Angualrjs 1.1

You have in your code:
$scope.options = [{
"id": "id1",
"name": "p1"
}, {
"id": "id2",
"name": "p2"
}];
$scope.data = [{
"name": "data1",
"option": {
"id": "id1",
"name": "p1"
}
}];
but Angular doesn't know that first option object used in $scope.options collection is same as option used in $scope.data.
I can suggest two solutions:
In $scope.data keep only option identifier "option": "id1" and in ng-options use d.id as d.name for d in options
In ng-options use "ng-options="d as d.name for d in options" and initialize $scope.data options like "option": $scope.options[0], but since it is coming from backend you may need to fix references manually.
Options 1 is better IMHO.
EDIT: Example JSFIDDLE was created in Angular 1.1, if you use Angular 1.2 or later #Satpal track by answer is also good option (no pun).

Related

Using ng-if and ng-repeat correctly

I have a rudimentary understanding of AngularJS and have a couple (possibly stupid) questions about ng-if and ng-repeat.
If I have a ng-repeat that looks like this:
For all containers without titles, would the ng-repeat produce those containers and not show them? Or do they simply don't exist? The reason I ask is I've tried to replace ng-if with ng-show, but it does not produce the same outcome of "hiding" containers that do not have titles.
Is there a way to code a ng-if to say if the next container has no title, then do something. I tried something like ng-if="item.title=='' && $index+1", without any luck.
Any suggestions?
My data looks like this:
"_sections": [{
"_bootstrap_cells": 6,
"_count": 2,
"visible": true,
"columns": [{
"fields": [{
"name": "type_of_account",
"type": "field"
}, {
"name": "routing_transit_number",
"type": "field"
}]
}, {
"fields": [{
"name": "type_of_payment",
"type": "field"
}, {
"name": "check_digit",
"type": "field"
}]
}],
"caption": "Direct Deposit",
"id": "b456b9d2137ac340177c36328144b0ef"
}, {
"_bootstrap_cells": 12,
"_count": 1,
"visible": true,
"columns": [{
"fields": [{
"name": "account_number",
"type": "field"
}, {
"name": "account_title",
"type": "field"
}, {
"name": "financial_institution_name",
"type": "field"
}]
}],
"caption": "",
"id": ""
}
}]
The first section has two columns and a bootstrap cell value of 6 for each column, the second section only has one column and a bootstrap cell of 12. Since the second doesn't have a caption, I want it to be appended to the first section, but keep both sections' bootstrap formatting.
If containers is an array then it does not have a title property. You need to check the title on each item.
Also note that ng-if will not hide the content, but remove it or not insert it into the DOM. The counterpart of ng-show is ng-hide.
angular.module('appModule', [])
.controller('MyController', [function() {
this.containers = [{
aaa: 1,
title: 'One'
}, {
aaa: 2,
title: ''
}, {
aaa: 3,
title: 'Three'
}]
}]);
angular.bootstrap(window.document, ['appModule'], {
strictDi: true
});
<div ng-controller="MyController as myCtrl">
<div ng-repeat="item in myCtrl.containers track by $index">
<div ng-if="item.title!=''">{{$index}}. {{item.title}}</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script>

ng-selected is not working with ng-model in select box - Angularjs [duplicate]

This question already has answers here:
AngularJS: ng-selected doesn't show selected value [duplicate]
(2 answers)
Closed 4 years ago.
While ng-model is used in select box and ng-selected is also used in options with some condition that time ng-selected is not working.
If I will remove ng-model than ng-selected is working, but if i will remove ng-model than how I should get the value of select box in controller.
Please help !
Here is my code...
HTML:
<select class="form-control" ng-change="accessModeSelected()">
<option ng-selected="mode.status == '1'" ng-repeat="mode in storageResult.accessMode" ng-value="mode.name" name="accessMode{{$index}}" id="accessMode">
{{mode.name}}
</option>
</select>
AngularJS:
$scope.storageResult = {
"storageAccount":"Enable",
"user": "sdcard",
"pass": "sdcard",
"wifiIP": "0",
"ipAddr": "0",
"accessMode": [
{"name": "Local Storage","status": "0"},
{"name":"WiFi Storage", "status": "1"},
{"name":"Internet Storage", "status": "0"}
]
}
Use ng-options and ng-init(for setting default value) instead of ng-repeat.
ng-options is specifically for select
<select class="form-control" ng-init="statusselect='WiFi Storage'" ng-model="statusselect" ng-options="mode.name as mode.name for mode in storageResult.accessMode">
</select> Selected Value : {{statusselect}}
FIDDLE
Edit: Using ng-repeat
I would prefer ng-options,but if you want to use ng-selected with ng-repeat you'll need provide a default selected value to ng-model from your controller
<select class="form-control" ng-model="statusselect">
<option ng-selected="{{mode.name == statusselect}}" ng-repeat="mode in storageResult.accessMode" value="{{mode.name}}" name="accessMode{{$index}}" id="accessMode">
{{mode.name}}
</option>
</select> Selected Value : {{statusselect}}
Inside Controller
$scope.storageResult = {
"storageAccount":"Enable",
"user": "sdcard",
"pass": "sdcard",
"wifiIP": "0",
"ipAddr": "0",
"accessMode": [
{"name": "Local Storage","status": "0"},
{"name":"WiFi Storage", "status": "1"},
{"name":"Internet Storage", "status": "0"}
]
}
$scope.statusselect = $scope.storageResult["accessMode"][1]["name"];
FIDDLE
Use ng-options instead of ng-repeat
<select ng-model="status" ng-options="mode.status as mode.name for mode in storageResult.accessMode">
and In controller
app.controller("dobController", ["$scope", "$http",
function($scope, $http) {
$scope.storageResult = {
"storageAccount": "Enable",
"user": "sdcard",
"pass": "sdcard",
"wifiIP": "0",
"ipAddr": "0",
"accessMode": [{
"name": "Local Storage",
"status": "0"
}, {
"name": "WiFi Storage",
"status": "1"
}, {
"name": "Internet Storage",
"status": "0"
}]
};
$scope.status = '1';
}
]);
DEMO
I'm sure there are many ways to answer this question and a lot of answers have been provided,but based on OP's question on how to send 'mode.name' into ng-model I've explained below using ng-options.
In your JS
var app = angular.module('todoApp', []);
app.controller("dobController", ["$scope", "$http",
function($scope, $http) {
$scope.storageResult = {
"storageAccount": "Enable",
"user": "sdcard",
"pass": "sdcard",
"wifiIP": "0",
"ipAddr": "0",
"accessMode": [{
"name": "Local Storage",
"status": "0"
}, {
"name": "WiFi Storage",
"status": "1"
}, {
"name": "Internet Storage",
"status": "0"
}]
};
$scope.status = $scope.storageResult.accessMode[0].name;
$scope.selectedItem = '';
}
]);
In your HTML to bind mode name to ng-model follow this.
<select ng-model="status" ng-options="mode.name as mode.name for mode in storageResult.accessMode">
To bind entire object you can try below syntax
<select ng-model="status" ng-options="mode as mode.name for mode in storageResult.accessMode">
For this make small change in your JS $scope.status like
$scope.status = $scope.storageResult.accessMode[0];
Here is a DEMO plunker

What would be angular ng-option equivalent of this select?

I am struggling to get this into an ng-option. Is it even possible?
<select ng-model="detail_type_id">
<optgroup ng-repeat="type in data.detailTypes" label="{{type.name}}">
<option ng-repeat="t in type.children" value="{{t.id}}">{{t.name}}</option>
</optgroup>
</select>
DetailTypes looks like this:
[
{"id":7,
"parent_id":null,
"name":"Contact",
"children":[
{"id":8,
"parent_id":7,
"name":"Address",
"children":[]
},
{"id":12,
"parent_id":7,
"name":"Something else",
"children":[]
}
]},
{"id":16,
"parent_id":null,
"name":"Other",
"children":[
{"id":10,
"parent_id":16,
"name":"Remarks",
"children":[]}
]
}
]
Child id needs to be selected. Nesting cannot be deeper.
The ngOptions directive does not work with multidimensional objects. So you need to flatten your array to use it.
I wrote a filter for that:
app.filter('flatten' , function(){
return function(array){
return array.reduce(function(flatten, group){
group.children.forEach(function(child){
child.groupName = group.name;
flatten.push(child)
})
return flatten;
},[]);
}
})
And the HTML part would be like this:
<select ng-model="detail_type_id"
ng-options="item.id as item.name
group by item.groupName for item
in data.detailTypes | flatten track by item.id">
</select>
Plunker (version #1 with filter):
https://plnkr.co/edit/dxi7j8oxInv2VRJ1aL7F
I also modified your object to be like this:
[{
"id": 7,
"parent_id": null,
"name": "Contact",
"children": [{
"id": 8,
"parent_id": 7,
"name": "Address",
"children": []
}, {
"id": 12,
"parent_id": 7,
"name": "Something else",
"children": []
}]
}, {
"id": 16,
"parent_id": null,
"name": "Other",
"children": [{
"id": 10,
"parent_id": 16,
"name": "Remarks",
"children": []
}]
}]
EDIT:
After suggestion I wrote another version without the filter, but flattening the array inside the controller.
Additional Controller JS:
$scope.flattenDetailTypes = flattenDetailTypes($scope.data.detailTypes);
function flattenDetailTypes(array){
return array.reduce(function(flatten, group){
group.children.forEach(function(child){
child.groupName = group.name;
flatten.push(child)
})
return flatten;
},[]);
}
Markup:
<select ng-model="detail_type_id"
ng-options="item.id as item.name group by item.groupName for item in flattenDetailTypes track by item.id"></select>
Plunker (version #2 without filter):
https://plnkr.co/edit/D4APZ6

how to create a combination of two properties as "name" in ng-options

Normally what we do is
...}}_{{$index}}" ng-options="option.serial_no as option.NameRelation for option in fullFamilydetails" ng-model="obj.ch6a_decl_fam_memb_id">
and on Java I am doing
...
familyDetails.put("NameRelation", Emp_FamilyInfoTemp.getName()+"-"+Emp_FamilyInfoTemp.getRelation());
}else{
...
As you see I am handling it on java to show "NAME" - "RELATION" pair as "name of ng-options"
but what I want is to keep NAME and RELATION as different properties in json but show a combination of them while creating ng-options, all and all I want to create the same effect while keeping the properties separate.
Current Sample Json
[{"DOB":"2014-09-03 00:00:00.0","NameRelation":"MaleChildTest-Son","SERIAL_NO":55213,"AGE":"0"},{"DOB":"2014-09-12 00:00:00.0","NameRelation":"FemaleChildTest-Daughter","SERIAL_NO":55216,"AGE":"0"},{"DOB":"2014-09-12 00:00:00.0","NameRelation":"MaleChildTesEmp-Son","SERIAL_NO":55217,"AGE":"0"},{"DOB":"2014-09-12 00:00:00.0","NameRelation":"FemaleChildEmployeeTest-Daughter","SERIAL_NO":55218,"AGE":"0"},{"DOB":"","NameRelation":"Test-Father","SERIAL_NO":55219,"AGE":"0"}]
supposed JSON
[{"DOB":"2014-09-03 00:00:00.0","Name":"MaleChildTest","Relation":"Son","SERIAL_NO":55213,"AGE":"0"}....]
In dropdown I want Name-Relaiton as "name" of options.
DEMO
<select ng-options="option.serial_no as label(option.Name, option.Relation) for option in fullFamilydetails" ng-model="obj"></select>
In your JS:
angular.module("SO29137733", [])
.controller("MainCtrl", function ($scope) {
$scope.fullFamilydetails = [{
"DOB": "2014-09-03 00:00:00.0",
"Name": "MaleChildTest",
"Relation": "Son",
"SERIAL_NO": 55213,
"AGE": "0"
}, {
"DOB": "2014-09-03 00:00:00.0",
"Name": "MaleChildTest",
"Relation": "Son",
"SERIAL_NO": 55213,
"AGE": "0"
}];
$scope.label = function (name, relation) {
return name + "-" + relation;
}
});
Another option:
DEMO
<select>
<option ng-repeat="option in options" value="{{option.serial_no}}">
{{option.name + " "+option.relation}}
</option>
</select>
In your JS:
angular.module("SO29137733", [])
.controller("MainCtrl", function($scope){
$scope.options = [{
serial_no : "123",
name : "hi",
relation: "parent"
},
{
serial_no : "1233",
name : "sa",
relation: "sdf"
}];
})
If you want to show it as single pair of option then do as below,
ng-options="option.serial_no as (option.name+' '+ option.relation) for option in fullFamilydetails"

AngularJS: Preselecting Options on Multiple Select

I'm trying to preselect options on my multiselect. In order to make my case clear, I've made a JSFiddle.
<select ng-model="properties" id="props" multiple
ng-options="option.name group by option.category for option in options"></select>
Unfortunately, I am bound by the way the object is received, so I guess I need the ng-options attribute.
Does anybody have an idea how I can get both 'Captain America' and 'Dr. Doom' selected on load?
Try changing your controller code to:
function TestCtrl($scope) {
var myOptions = [{
"id": "4",
"name": "Captain America",
"categoryId": "1",
"category": "Heroes"
}, {
"id": "5",
"name": "Iron Man",
"categoryId": "1",
"category": "Heroes"
}, {
"id": "10",
"name": "Magneto",
"categoryId": "2",
"category": "Vilains"
}, {
"id": "9",
"name": "Dr. Doom",
"categoryId": "2",
"category": "Vilains"
}];
$scope.options = myOptions;
$scope.properties = [myOptions[0], myOptions[3]];
}
Explanation: you are setting your selected options (properties) to different instances of the objects than the ones that compose the full list. Use the same object references as shown above.
You are super close, two changes. Define the attributes in your controller like this
$scope.properties = ["Captain America", "Dr. Doom"];
And add a small piece to your ng-options like this
ng-options="option.name as option.name group by option.category for option in options"
Your option.name as will determine what the saved feature looks like in $scope.properties

Resources