I have two select menus . One for country selection and other for state. I need to update states based country selected. I am able to log states but not able to list them in select menu.Please help.
Angular:
angular.module('demoApp', []).controller('DemoController', function($scope) {
$scope.countries = [
{ label: 'Please select', value: 0 },
{ label: 'India', value: 1 },
{ label: 'US', value: 2 }
];
$scope.data = [{'1':[{ label: 'Delhi', value: 0 },{ label: 'Mumbai', value: 1 },{ label: 'Chennai', value: 2 }]},
{'2':[{ label: 'Alabama', value: 3 },{ label: 'Alaska', value: 4 },{ label: 'Arizona', value: 5 }]}];
$scope.vm = {states: []};
$scope.updateStates = function(countryCode){
$scope.vm.states = $scope.data[countryCode-1];
console.log($scope.vm.states);
};
$scope.correctlySelected = $scope.countries[0];
});
HTML:
<body ng-app="demoApp">
<div ng-controller="DemoController">
<select ng-model="correctlySelected" ng-change="updateStates(correctlySelected.value)" ng-options="opt as opt.label for opt in countries">
</select>
<select ng-options="opt as opt.label for opt in vm.states">
</select>
</div>
</body>
JS Bin:
http://jsbin.com/pafosewedo/1/edit?html,js,console,output
You need to add ng-model to your states <select> - this is required when you are using ng-options
You also have an inconvenient model for the states data. Each element of the data array that corresponds to the country's states is an object with a changing key whose value is an array of states. You could make it work, but it's better to change it to something more reasonable:
$scope.data = {
1: [{ label: 'Delhi', value: 0 }, {...}, ],
2: [{...}, {...}, ] // same for US
}
Then it would work with how you specified your ng-options for states, and you wouldn't have to deal with indices:
$scope.updateStates = function(countryCode){
$scope.vm.states = $scope.data[countryCode]; // access by property
};
I think, that you should use some filter like that if you don't want to change your model:
.filter('stateFilter', function() {
return function(states, countryID) {
var filtered = [];
angular.forEach(states, function(state){
if(state.value === countryID)
filtered.push(state);
});
return filtered;
};
});
to filter out all values that have value equal to selected country.value in first select control.
To use that filter you need to modify your ng-repeat directive value in state select control:
ng-options="state as state.label for data | stateFilter:correctlySelected"
I came up with the following solution, view my JSBin
This solutions works by setting the countryCode in the scope when we are updatingStates.
$scope.updateStates = function(countryCode){
$scope.countryCode = countryCode;
$scope.vm.states = $scope.data[countryCode-1];
console.log($scope.vm.states[countryCode]);
};
This change is then reflected in the view.
<select>
<option ng-repeat='i in vm.states[countryCode]'> {{i.label}}
</option>
</select>
Related
I have seen infinity of post to try to choose by default an option in a dropdown. But I have not been able to achieve it. I have an array of some countries.
$scope.regions =
[
{
name: "COLOMBIA",
code: 5
},
{
name: "ARGENTINA",
code: 6
},
{
name: "BRAZIL",
code: 7
}
];
I have this variable:
$scope.selectThisId={
"id":6,
"animal":'dog',
"variable":'xxx32'
};
I need the dropdown value to be equal to the id attribute of the
$scope.region=$scope.selectThisId.id;
variable.
http://plnkr.co/edit/nmc8iLz6BIFac0Swfth8?p=preview
Working demo: http://plnkr.co/edit/zhye91pDUEMgaZnXZGWE?p=preview
You basically create a default region by doing
$scope.select = $scope.selectThisId.id;
$scope.regionSelected = {};
then create a select tag with ng-options, binding it to the model, and calling ng-init on the model.
<select ng-options="item as item.name for item in regions track by item.code"
ng-model="regionSelected" ng-init="regionSelected.code = select">
</select>
You can add a filter to your controller to get the default region (don't forget to add $filter after $scope):
$scope.defaultValue = $filter('filter')($scope.regions, {code: $scope.selectThisId.id}, true)[0];
and then add this to your select in your view
ng-init="select = defaultValue"
Demo
DEMO
var myapp = angular.module('myapp', []);
myapp.controller('FirstCtrl', function ($scope) {
$scope.regions =
[
{
name: "COLOMBIA",
code: 5
},
{
name: "ARGENTINA",
code: 6
},
{
name: "BRAZIL",
code: 7
}
];
$scope.selectThisId={
"id":6,
"animal":'dog',
"variable":'xxx32'
};
$scope.region=$scope.selectThisId.id;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp">
<fieldset ng-controller="FirstCtrl">
<select
ng-options="item.code as item.name for item in regions"
ng-model="region"></select>
</fieldset>
</div>
So I'm using KnockoutJS to populate a <select> with options and to get the value of the select.
<select data-bind="enable: cols1().length > 0, options: cols1(), optionsText: 'name', value: jCol1" id="col1"></select>
The variable cols1 holds objects with the simple format of { name: "name" } just because it needs to be objects for some of the other stuff I do on the page. Is there any way to set the value of the select from outside of the data-binds on this element?
The value part of the binding says:
Store a reference to an item that is in cols1 in jCol1
If you want to change the selection from outside of the UI, you'll have to set jCol1 to a value that is in the cols1 array. If you try to set it to anything else, knockout will reset it to the first value immediately. Switch out the commented lines of code in the example below to see this happen:
var ViewModel = function() {
this.options = ko.observableArray([
{ name: "Item 1" },
{ name: "Item 2" },
{ name: "Item 3" }
]);
this.selection = ko.observable();
this.selection.subscribe(function(newValue) {
console.log(newValue)
});
this.changeSelectionFromOutside = function() {
// This does not work because knockout does not do a
// deep comparison of objects
// this.selection({ name: "Item 3" });
// This _does_ work, because it references one of the
// options objects
this.selection(this.options()[2]);
}.bind(this);
};
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: options, value: selection, optionsText: 'name'"></select>
<button data-bind="click: changeSelectionFromOutside">
Set option 3
</button>
Now, you can also choose to just store a string ID (or other primitive) of your selection. This makes it easier to set things from the outside, because you only need the ID instead of a reference to the actual item:
var ViewModel = function() {
this.options = ko.observableArray([
{ name: "Item 1" },
{ name: "Item 2" },
{ name: "Item 3" }
]);
this.selection = ko.observable();
this.selection.subscribe(function(newValue) {
console.log(newValue)
});
this.changeSelectionFromOutside = function() {
this.selection("Item 3");
}.bind(this);
};
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: options, value: selection, optionsText: 'name', optionsValue: 'name'"></select>
<button data-bind="click: changeSelectionFromOutside">
Set option 3
</button>
Let's use the states example:
//list of US states in array
self.usStates = [
{ StateName: 'Alabama', Abbr: 'AL' },
{ StateName: 'Alaska', Abbr: 'AK' },
...
//observable from that array
self.States = ko.observableArray(self.usStates);
//the selected state
self.selectedState = ko.observable();
//set selectedState from some value received from server
self.selectedState(self.States.find("Abbr", { StateName: "", Abbr: '<<Value i.e. TX>>' }).Abbr);
//finds TX, sets state to 'Texas'
//find custom function used to find specific object in array
ko.observableArray.fn.find = function (prop, data) {
var valueToMatch = data[prop];
return ko.utils.arrayFirst(this(), function (item) {
return item[prop] === valueToMatch;
});
};
This may be overly complicated for what you're looking to do, but this is how I do it when I want to choose a value from a select based on a value from the record in the database.
I am new to AngularJS and trying to get Selected Text and Value from Dropdown. I followed a lot of tutorials with still unable to get there. SelectedValue and SelectedText are always undefined. Below is my code:
Html:
<div ng-app="SelectApp">
<div ng-controller="selectController">
<select name="category-group" id="categoryGroup" class="form-control" ng-model="itemSelected" ng-change="onCategoryChange(itemSelected)">
<option value="0">Select a category...</option>
<option ng-repeat="category in categories" value="{{category.id}}"
ng-disabled="category.disabled" ng-class="{'mainCategory' : category.disabled}">
{{category.name}}
</option>
</select>
</div>
Js:
'use strict';
var app = angular.module('SelectApp', [ ]);
app.controller('selectController', ['$scope', '$window', function ($scope, $window) {
$scope.categories = [
{ id: 1, name: "- Vehicles -", disabled: true },
{ id: 2, name: "Cars" },
{ id: 3, name: "Commercial vehicles", disabled: false },
{ id: 4, name: "Motorcycles", disabled: false },
{ id: 5, name: "Car & Motorcycle Equipment", disabled: false },
{ id: 6, name: "Boats", disabled: false },
{ id: 7, name: "Other Vehicles", disabled: false },
{ id: 8, name: "- House and Children -", disabled: true },
{ id: 9, name: "Appliances", disabled: false },
{ id: 10, name: "Inside", disabled: false },
{ id: 11, name: "Games and Clothing", disabled: false },
{ id: 12, name: "Garden", disabled: false }
];
$scope.onCategoryChange = function () {
$window.alert("Selected Value: " + $scope.itemSelected.id + "\nSelected Text: " + $scope.itemSelected.name);
};
}]);
And one more thing, I have defined my first item as Select a category... then Why first item in Dropdown is always empty.
Below is my fiddle sample.
http://jsfiddle.net/Qgmz7/136/
That's because, your model itemSelected captures the current value of your select drop down which is nothing but the value attribute of your option element. You have
<option ng-repeat="category in categories" value="{{category.id}}">
in your code, so in the rendered version, you'll get
<option ng-repeat="category in categories" value="0">
but you're expecting itemSelected to be your category object and any attempt to query id or other property will return undefined.
You can use ng-options with group by with little bit of change to your data or you can use normal ng-repeat, get the selectedIndex and lookup the category object from your categories list using that index. Showcasing the first approach here.
HTML
<select name="category-group" id="categoryGroup"
ng-model="itemSelected" ng-change="onCategoryChange(itemSelected)"
ng-options="category.name group by category.group for category in categories">
</select>
Updated Data
$scope.categories = [
{ id: 0, name: "Select a category..."},
{ id: 1, name: "Cars", group : "- Vehicles -" },
{ id: 2, name: "Commercial vehicles", group : "- Vehicles -" },
{ id: 3, name: "Motorcycles", group : "- Vehicles -" }
];
$scope.itemSelected = $scope.categories[0];
Instead of disabled property, you can add a group property which can be used in group by.
Here' an updated Fiddle to illustrate the idea.
You should use ng-options to set object to your ng-model value on change of you select options.
Markup
<select name="category-group" id="categoryGroup" class="form-control"
ng-model="itemSelected" ng-change="onCategoryChange(itemSelected)"
ng-options="category.name for category in categories">
<option value="0">Select a category...</option>
</select>
Fiddle Here
Update
For persisting style you have to use ng-repeat there, in that case you will only have id binded to your ng-model and while retrieving whole object you need to filter your data.
$scope.onCategoryChange = function () {
var currentSelected = $filter('filter')($scope.categories, {id: $scope.itemSelected})[0]
$window.alert("Selected Value: " + currentSelected.id + "\nSelected Text: " + currentSelected.name);
};
Updated Fiddle
<div ng-app="SelectApp">
<div ng-controller="selectController">
<select ng-change='onCategoryChange()' ng-model="itemSelected" ng-options="category.name for category in categories">
<option value="">-- category --</option>
</select>
</div>
//http://jsbin.com/zajipe/edit?html,js,output
A little change in your onCategoryChange() should work:
$scope.onCategoryChange = function () {
$window.alert("Selected Value: " + $scope.categories[$scope.itemSelected - 1].id + "\nSelected Text: " + $scope.categories[$scope.itemSelected -1].name);
};
JSFiddle: http://jsfiddle.net/Qgmz7/144/
ngChange only returns the value of your selected option and that's why you don't get the whole data.
Here's a working solution without changing your markup logic.
Markup:
<select
name="category-group"
id="categoryGroup"
class="form-control"
ng-model="id"
ng-change="onCategoryChange(id)">
ngChange handler:
$scope.onCategoryChange = function (id) {
//get selected item data from categories
var selectedIndex = $scope.categories.map(function(obj) { return obj.id; }).indexOf( parseInt(id) );
var itemSelected = $scope.categories[selectedIndex];
$window.alert("Selected Value: " + itemSelected.id + "\nSelected Text: " + itemSelected.name);
};
Another solution (little bit dirty) would be to change only the value of your options into something like this:
<option .... value="{{category.id}}|{{category.name}}">
...and inside your actual ngChange handler, just split the value to get all the values as an array:
$scope.onCategoryChange = function (itemSelected) {
$scope.itemSelected = itemSelected.split('|'); //string value to array
$window.alert("Selected Value: " + $scope.itemSelected[0] + "\nSelected Text: " + $scope.itemSelected[1]);
};
Here very Simple and easy code What I did
<div ng-app="myApp" ng-controller="myCtrl">
Select Person:
<select ng-model="selectedData">
<option ng-repeat="person in persons" value={{person.age}}>
{{person.name}}
</option>
</select>
<div ng-bind="selectedData">AGE:</DIV>
<br>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl',myCtrlFn);
function myCtrlFn($scope) {
$scope.persons =[
{'name': 'Prabu','age': 20},
{'name': 'Ram','age': 24},
{'name': 'S','age': 14},
{'name': 'P','age': 15}
];
}
</script>
If I want to set the value of the combobox I have tried this:
controllercode:
$scope.streettypeMockData = [{
name: 'Street',
value: 'Street'
}, {
name: 'Avenue'
}, {
name: 'Crescent'
}, {
name: 'Drive'
}, {
name: 'Road'
}, {
name: 'Highway'
}];
var sel = "Street";
var selectedValue = {
name: sel
};
$scope.streetTypeSelected = selectedValue;
Can anyone tell me why this does not work? see also http://plnkr.co/edit/4ISL8A1cNGCtafsc0leX?p=preview
The code has a few issues:
The ng-options select the name, while the ng-model points to an object. Better use streetType as streetType.name for streetType in streettypeMockData to select the entire object.
In this case, the initial value will not be honoured because Angular will try to compare objects by reference; use track by.
The full <select> should be:
<select class="form-control" ng-model="streetTypeSelected"
ng-options="streetType as streetType.name for streetType in streettypeMockData track by streetType.name">
See forked plunker.
You can simple use ng-init like this
<select ng-init="streetTypeSelected = streettypeMockData[0]" class="form-control" ng-model="streetTypeSelected" ng-options="streetType.name for streetType in streettypeMockData">
</select>
Working Demo
Also you can do Like as shown below
var app = angular.module('myApp', []);
app.controller('MainCtrl', function ($scope) {
$scope.streettypeMockData = [
{name: 'Street', value: 'Street'},
{name: 'Avenue'},
{name: 'Crescent'},
{name: 'Drive'},
{name: 'Road'},
{name: 'Highway'}
];
$scope.streetTypeSelected = $scope.streettypeMockData[0];
});
Working Demo
Also take a look at this
https://docs.angularjs.org/api/ng/directive/select
I'm working with ngOptions to display a select element, and want to connect the model to the value that's set as the value in ngOptions.
var app = angular.module('test', []);
app.controller('TestCtrl', ['$scope',
function ($scope) {
//Use random to simulate different data from an API
$scope.default = Math.floor(Math.random()*3);
$scope.options = [
{
id: 0,
name: "Option 1"
},
{
id: 1,
name: "Option 2"
},
{
id: 2,
name: "Option 3"
}
];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test">
<div ng-controller="TestCtrl">
<select ng-model="default" ng-options="val.name for val in options track by val.id">
</select>
<pre>Default should be ID {{default}}, or Option {{default+1}}
</div>
</div>
I've tried using track by, select as, and I've found two solutions that work, but are not ideal.
Ideally, I'd be able to set default
Solution 1:
// Loop through entire array of objects
$scope.options.forEach(function (v, k) {
// Compare ID to what the default should be
if (v.id === $scope.default) {
// Set object to default
$scope.default = v;
return true;
}
});
Solution 2:
JS
$scope.options = {
"Option 1": 0,
"Option 2": 1,
"Option 3": 2
};
HTML
<select ng-model="default" ng-options="value as key for (key, val) in options">
The thing that's tough about this solution is it only works if the object has no more than two values, since a key cannot be an object.
Is there any way to have Angular set a default by key, without having to include the entire object?
try it like this
<select ng-options="item.id as item.name for item in options" ng-model="selected"></select>
then in controller
$scope.selected = 1;
similar plunkr example
var app = angular.module('test', []);
app.controller('TestCtrl', ['$scope',
function ($scope) {
//Use random to simulate different data from an API
$scope.options = [
{
id: 0,
name: "Option 1"
},
{
id: 1,
name: "Option 2"
},
{
id: 2,
name: "Option 3"
}
];
$scope.default = $scope.options[Math.floor(Math.random()*3)];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test">
<div ng-controller="TestCtrl">
<select ng-model="default" ng-options="val.name for val in options">
</select>
<pre>Default should be ID {{default.id}}, or Option {{default.id+1}}
</div>
</div>