I have created an AngularJS application with select box, The application with select is working fine, but the problem is that I want option group like thing in select which is selectable, since i am aware that the option group feature in select is not selectable, I made similar stuff using CSS, when i put the values statically its working fine, but dynamically I am not able to show the child details
JSFIDDLE
can anyone please tell me some solution for this
angular.module('Test1',[])
.controller('Foo', function($scope) {
$scope.regionsData = {
"regions": [
{
"regionId": 15,
"regionName": "Kerala",
"places": [
{
"placeId": 21,
"placeName": "Trivandrum"
},
{
"placeId": 22,
"placeName": "Kollam"
}]
},
{
"regionId": 16,
"regionName": "Chennai",
"places": [
{
"placeId": 23,
"placeName": "Kanchipuram"
},
{
"placeId": 24,
"placeName": "Guindy"
}]
}
]
}
});
.region {
font-weight: bold
}
.place {
padding-left: 25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="Test1">
<div ng-controller="Foo">
<b>DYNAMIC<b><br>
HOW CAN I DISPLAY THE CHILD DETAILS<br>
<select ng-model="data.selectedDocumentType" class="region" ng-options="region as region.regionName for region in regionsData.regions"> </select>
<br><br><b>STATIC<b><br>
THIS IS WHAT I WANT TO ACHIEVE<br>
<select>
<option class="region">Kerala</option>
<option class="place">Trivandrum</option>
<option class="place">Kollam</option>
<option class="region">Chennai</option>
<option class="place">Kanchipuram</option>
<option class="place">Guindy</option>
</select>
</div>
</div>
FYI, google chrome doesn't allow adding css to option elements, see this
answer
I found this to work:
example
as mentioned in the comments, I re formatted the data in a simpler fashion, using loops on the original variable:
$scope.test = [];
$scope.regionsData.regions.forEach(function(val, key) {
$scope.test.push(val.regionName);
val.places.forEach(function(val, key){
$scope.test.push(val.placeName);
})
})
and in html:
<select ng-model="data.selectedDocumentType" class="region" ng-options="region for region in test"> </select>
to overcome chrome's issue, and apply css, a better approach is to use <ul> with <li> to make the dropdown.
here's an example of how to create the html, making in look like a dropdown is out of the scope of your question:
turn select into unordered-list fiddle
see this question on how to turn a ul into a dropdown
Related
I am trying to make dependent dropdown using JSON data
Used (for in) to get the key to integrate it in the dropdown but didn't work,whatever i searched every time json data is getting accessed by key to get the value in this structure i am able to get it in dropdown [{name:"india"},{name:"usa"}].But with current json structure i am not able to do it.
HTML:-
<div ng-controller="myCtrl3">
<select>
<option>Select Country</option>
<option ng-repeat="country in chooseCountries"></option>
<option ng-repeat="states in country"></option>
<option ng-repeat="city in states"></option>
</select>
</div>
JS:-
app.controller('myCtrl3',function($scope,$http){
$http({
url:'js/country.json',
method:'GET'
})
.then(function(response){
$scope.chooseCountries = response.data;
});
});
JSON(country.json):-
[{
"INDIA": {
"KARNATAKA": ["BANGALORE", "UDUPI", "MANGALORE"],
"TELENGANA": ["HYDERABAD", "GUNTUR", "SHANKERPALLY"]
},
"USA": {
"CALIFORNIA": ["SAN JOSE", "SAN HOSE", "NEW YORK"],
"FLORIDA": ["MIAMI", "DENVER"],
"INDIAPOLIS": ["INDIANA", "MASACHUTTEUS"]
},
"AUSTRALIA": {
"NEW SOUTH WALES": ["SYDNEY", "BRISBANE"],
"QUEENSLAND": ["PERTH", "VICTORIA"],
"WESTERN AUSTRALIA": ["MELBOURNE", "MCG"]
}
}]
i want the output first dropdown should show INDIA,USA,AUSTRALIA if i click INDIA second dropdown should show KARNATAKA AND TELENGANA in the third dropdown list if i click KARNATAKA it should show BANGALORE,UDUPI,MANGALORE.Didn't got any error but coudn't get the desired output.
I'm guessing you can't alter the format of the returned JSON. If that is the case, you don't have a nicely formed object hierarchy that you can use so instead you'll have to fall back to using (key, value). Below is a simple example of how you can accomplish what you are after.
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.countryChoices = [{
"INDIA": {
"KARNATAKA": ["BANGALORE", "UDUPI", "MANGALORE"],
"TELENGANA": ["HYDERABAD", "GUNTUR", "SHANKERPALLY"]
},
"USA": {
"CALIFORNIA": ["SAN JOSE", "SAN HOSE", "NEW YORK"],
"FLORIDA": ["MIAMI", "DENVER"],
"INDIAPOLIS": ["INDIANA", "MASACHUTTEUS"]
},
"AUSTRALIA": {
"NEW SOUTH WALES": ["SYDNEY", "BRISBANE"],
"QUEENSLAND": ["PERTH", "VICTORIA"],
"WESTERN AUSTRALIA": ["MELBOURNE", "MCG"]
}
}];
$scope.selectedCountry = {};
$scope.selectedState = {};
$scope.selectedCity = '';
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div>
<select ng-model="selectedCountry" ng-options="value as key for (key, value) in countryChoices[0]"></select>
</div>
<div>
<select ng-model="selectedState" ng-options="value as key for (key,value) in selectedCountry"></select>
</div>
<div>
<select ng-model="selectedCity" ng-options="value as value for value in selectedState"></select>
</div>
</div>
In order for that to work, your json data should be like this:
[{
country: "INDIA",
states: [
{
"KARNATAKA": {
cities: ["BANGALORE", "UDUPI", "MANGALORE"]
}
}
}]
Hope it helps...
I have my object selected via a selection box printed out on the page as the user selects the option.
However it currently prints the parent object and all other objects nested within the parent object.
A example of my array
$scope.productsandformats = [
{
"Pname": "parent",
"format": [
{"Fname": "child", "id": "4"},
{"Fname": "second child", "id": "5"}
]
}
];
My angular and html selection box
<select ng-model="formData.ProductType"
ng-options="product.Pname for product in productsandformats">
<option value="">- Please Choose -</option>
</select>
<pre class="col-sm-12 ng-binding">
{{ formData }}
</pre>
so currently when I select parent I get
{"ProductType":{"Pname":"parent","format":[{"Fname":"child","id":"4"},{"Fname":"second child","id":"5"}]}}
What I expect to see
{"ProductType":{"Pname":"parent"}}
What I need
I just want to see the Pname so the top level objects eg parent, parent2, parent3 so on not the children objects.
How can I alter this to just show the top level object?
#George answer almost works
difficulty my second drop down should be populated with the child objects of the selected parent and the final string should read as following if select parent from first option then second child from second option.
ProductType: Pname: parent, formatType: Fname: child
**Angular code for both boxes, second populated with children of the selected parent **
<select ng-model="formData.ProductType"
ng-options="product.Pname for product in productsandformats">
<option value="">- Please Choose -</option>
</select>
<select ng-model="formData.formatType"
ng-options="format.Fname for format in formData.ProductType.format"
ng-if="formData.ProductType">
<option value="">- Please Choose -</option>
</select>
If you read the documentation on ngOptions you can use select as to specify was object gets set on the ngModel
For the second select I suggest having an ng-change on the first select to store that object in another variable on the scope that you can use for the second select.
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.productsandformats = [{
"Pname": "parent",
"format": [{
"Fname": "child",
"id": "4"
}, {
"Fname": "second child",
"id": "5"
}]
}];
$scope.formats = [];
$scope.productTypeChange = function() {
$scope.formats = $scope.productsandformats.find(ps => ps.Pname == $scope.formData.ProductType.Pname);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<select ng-model="formData.ProductType.Pname" ng-change="productTypeChange()" ng-options="product.Pname as product.Pname for product in productsandformats">
<option value="">- Please Choose -</option>
</select>
<select ng-model="formData.formatType" ng-options="format.Fname for format in formats.format" ng-if="formData.ProductType.Pname">
<option value="">- Please Choose -</option>
</select>
<pre class="col-sm-12 ng-binding">
{{ formData }}
</pre>
</div>
</div>
You can access first level object like this
<div ng-repeat='p in formData.productType'>
{{p.pname}}
</div>
In my project, i need to select multiple options from a drop down. My code looks something like this:
//Controller
$scope.data = [{id: 1, Country: Zambia},
{id: 2, Country: United Kingdom}
{id: 3, Country: USA}]
$scope.selectedCountry = [];
//view
<select name="multipleSelect" id="multipleSelect" ng-model=" selectedCountry" multiple
ng-options="country.country as country.country for country in data"></select>
<h4> {{selectedCountry}}</h4>
The context above works and i can select multiple options from the dropdown. This link helped me to achieve this.
The problem.
Now the problem i'm having is that when i select the options from the dropdown i need to be able to pass the id and country in the selectedCountry array and not just the country. so for instance in the above context when you select the first country , the information passed through the to the selectedCountry Array will be something like this ["zambia"] but really what i'm looking for is something like this
[{id: 1, Country Zambia}].
To solve this problem i attempted to do this in the view:
<select name="multipleSelect" id="multipleSelect" ng-model=" selectedCountry" multiple
ng-options="{Id: country.Id, Country: country.country } as country.country for country in data"></select>
<h4> {{selectedCountry}}</h4>
That worked well and the data passed to the selectedCountry array is an object like {id: 1, Country: zambia} but the issue is that i cannot select multiple options from the dropdown i can only select 1 option.
What am i doing wrong? and what is the best way to achieve this?
Thank you
I've found some mistakes in your code:
Your JSON data is invalid. JSON string values must be in double
quote, the same for keys {"key":"value"}. Every item in an array
must be splitted by commas.
The correct key for the country name is "Country".
I'm using Angular 1.4.8.
You can use a shorter version of your code by using: country.Country for country in data
Something like this:
(function() {
var app = angular.module("app", []);
app.controller("controller", ["$scope",
function($scope) {
$scope.selectedCountry = [];
$scope.data = [{
"id": 1,
"Country": "Zambia"
}, {
"id": 2,
"Country": "United Kingdom"
}, {
"id": 3,
"Country": "USA"
}];
}
]);
})();
div {
margin: 2px;
}
.largeversion {
border: solid 1px #FF0000;
}
.shortversion {
border: solid 1px #005500;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div data-ng-app="app">
<div data-ng-controller="controller">
<div class="largeversion">
<pre>ng-options="{Id: country.Id, Country: country.Country } as country.Country for country in data"</pre>
<select name="multipleSelect" id="multipleSelect" ng-model=" selectedCountry" multiple ng-options="{Id: country.Id, Country: country.Country } as country.Country for country in data"></select>
</div>
<div class="shortversion">
<pre>ng-options="country.Country for country in data"</pre>
<select name="multipleSelect" id="multipleSelect" ng-model=" selectedCountry" multiple ng-options="country.Country for country in data"></select>
</div>
<h4> {{selectedCountry}}</h4>
</div>
</div>
Trying to figure out why the model does not update when the bound selected option no longer exists. I would expect the model's property to update to undefined/null/empty string.
Situation: One select drives another select using filter. After selections are made, go to the original select and choose another option. Filter will remove the second select option as expected, but the model property on the second select will be unchanged.
Problem: When you go to pass the model, it will be populated with bad/previous values. In addition, using Angular validation, the select being required...the form is technically "valid" because the model has a value (the previous value) for the property.
HTML:
<select name="Category" ng-model="selectedCategory"
ng-options="item.name as item.name for item in categories">
<option value="">All Categories</option>
</select>
<select name="SubCategory" ng-model="selectedSubCategory"
ng-options="item.name as item.subCategory for item in categories | filter:selectedCategory">
<option value="">All SubCategories</option>
</select>
Model:
app.controller('MainCtrl', function($scope) {
$scope.categories = [{
"id": "1",
"name": "Truck",
"subCategory": "Telescope"
}, {
"id": "2",
"name": "Truck",
"subCategory": "Hazmat"
}, {
"id": "3",
"name": "Van",
"subCategory": "Mini"
}];
});
I'm fairly certain I could tie an ng-change function to the first to force it to update the model, but is there a better way?
Example Plunker demonstrating the problem
Try this way:
$scope.$watch('selectedCategory', function(selectedCategory){
$scope.selectedSubCategory = null;
});
I am trying to display an observable array in a dropdown, and when the user selects the option, I want to present a property of that view model. It seems simple. I have provided code and a link to Fiddle.
HTML:
<select data-bind="options: oCountries,
optionsText: 'name',
optionsValue: 'isocode',
value: selectedCountry">
</select>
Controlled by <span data-bind="value: selectedCountry.isocode"></span>
JS:
var countries = [{
"name": "Afghanistan",
"isocode": "AF",
"language": "English",
"crmdatacontroller": "CRM India"
}, {
"name": "Aland Islands",
"isocode": "AX",
"language": "Finnish",
"crmdatacontroller": "CRM Finland"
}]
var viewModel = {
oCountries: ko.observableArray(countries),
selectedCountry: ko.observableArray(['AX'])
};
ko.applyBindings(viewModel);
See also this fiddle
The optionsValue parameter controls what is written by the value binding. So, in your case, it will write the isocode to selectedCountry.
So, the simplest changes to your code would be to set selectedCountry to a normal observable and the appropriate isocode. Then, have your span use the text binding against selectedCountry.
Like this: http://jsfiddle.net/wxNrt/21/
Now, a couple other options available to you as well:
-if you leave off optionsValue in the binding, then it will set/read the object directly. In that case, you need to change how you are intially setting it.
http://jsfiddle.net/wxNrt/23/
-if you want to send/receive a key (like the isocode), then you can use optionsValue, but set up a dependentObservable to represent the actual object like:
http://jsfiddle.net/wxNrt/22/
-if you are dealing with a multi-select situation, then you want to use the selectedOptions binding instead of value, as described here: http://knockoutjs.com/documentation/selectedOptions-binding.html
I changed your markup to this:
<select data-bind="options: oCountries, optionsText: 'name', optionsValue: 'isocode', value: selectedCountry">
</select>
Controlled by <span data-bind="text: selectedCountry"></span>
And the script:
var countries = [
{
"name": "Afghanistan",
"isocode": "AF",
"language": "English",
"crmdatacontroller": "CRM India"},
{
"name": "Aland Islands",
"isocode": "AX",
"language": "Finnish",
"crmdatacontroller": "CRM Finland"}
]
var viewModel = {
oCountries: ko.observableArray(countries),
selectedCountry: ko.observable('AX')
};
ko.applyBindings(viewModel);
And the jsfiddle