how to populate two <selects> via ajax with a json - javascript

I am making a system and I came across the following doubt .. I have two being the first to select the brand of the vehicle and the second would be to select the model of the vehicle. but I would like to select the brand of the vehicle and the of the model to load the models of the vehicles for the selected brand.
i have onde archive .json with brand and models of cars.
exemple format json
"value":"ACURA","title":"Acura","models":[{"value":"CL_MODELS","title":"CL Models (4)"}]}
<select id="brand"></select>
<select id="models"></select>
so I populate the first with the tags so the second would be populated with the models referring to the selected brand.
I need it when I select, for example BMW, the second select only the models referring to BMW, and not all models.
How do you do this?
thanks :)

I don't know enough about how the data is being fetched, but I believe you're asking about manipulating it in a way that makes it usable by the 2 selects. Take a look at the example below:
var json = [{
"value": "ACURA",
"title": "Acura",
"models": [{
"value": "CL_MODELS",
"title": "CL Models (4)"
}]
},
{
"value": "TOYOTA",
"title": "Toyota",
"models": [{
"value": "TOYOTA_MODELS",
"title": "Toyota Models (4)"
}]
}
];
$(document).ready(function() {
$('#models').prop('disabled', true);
$('#brand')
.append($("<option></option>")
.attr("value", "")
.text(""));
$.each(json, function(index) {
$('#brand')
.append($("<option></option>")
.attr("value", json[index]["value"])
.text(json[index]["title"]));
});
$('#brand').change(function() {
process($(this).children(":selected").html());
});
});
function process(brand) {
$('#models').prop('disabled', false).find('option')
.remove()
.end();
var models = $.map(json, function(entry) {
if (entry["title"] === brand) {
return entry["models"];
}
});
$.each(models, function(index) {
$('#models')
.append($("<option></option>")
.attr("value", models[index]["value"])
.text(models[index]["title"]));
});
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="brand"></select>
<select id="models"></select>

//YOUR_JSON_DATA
//{"value":"ACURA","title":"Acura","models":[{"value":"CL_MODELS","title":"CL Models (4)"}]}
$.get( YOUR_JSON_DATA, function( data ) {
// Did you want data to be an array of brands?
for (let brand of data) {
$("#brand").append(`<option>${ brand.value }</option>`)
for (let models of brand.models) {
$("#models").append(`<option> ${ models.value } </option>`)
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="brand"></select>
<select id="models"></select>
Here is an example code snippet for ya. I hope it provides some clarity. Did you want the JSON data be an array?

Related

How Can I Populate Dropdown Select Element using getJSON

I want to populate dropdown select menu.
i need to get bankName and iINNo from this JSON
My JSON :
{"status":true,"message":"Request Completed","data":[{"id":1,"activeFlag":1,"bankName":"Union Bank of India","details":"Union Bank of India","iINNo":"607161","remarks":"","timestamp":"21/11/2016 16:00:00"},{"id":2,"activeFlag":1,"bankName":"Bank of India","details":"Bank of India","iINNo":"508505","remarks":"","timestamp":"21/11/2016 16:00:00"},],"statusCode":0}
My Javacript :
let dropdown = $('#Bank');
dropdown.empty();
dropdown.append('<option selected="true" disabled>Select Bank</option>');
dropdown.prop('selectedIndex', 0);
const url = 'http://cors-anywhere.herokuapp.com/';
// Populate dropdown with list of provinces
$.getJSON(url, function (data) {
$.each(data, function (res, code) {
console.info(res);
console.info(code);
dropdown.append($('<option></option>').attr('value', value.iINNo).text(index.bankName));
})
});
The array with bank data is under the property data inside the JSON. So the trick is to loop over that property - right now you loop over the entire JSON response, including the status and message properties.
You will get the individual bank object as the second argument item and then you can access it's properties and append it to your dropdown:
$.each(data.data, function (index, item) {
console.info('Bank Data: ', item);
dropdown.append($('<option></option>').text(item.bankName));
});
This should work
const banks = document.getElementById('banks');
banks.innerHTML = '<option selected="true" disabled>Select Bank</option>';
fetch('https://cors-anywhere.herokuapp.com/http://www.allindiaapi.com/HMESEVAAEPS/GetBankDetails?tokenkey=KzhnBIUi1wuM97yizKJ07WB3YwPSykyX9CjB6C6O5LRyClZ9YZl9NcIk5f6Fjna4')
.then(response => response.json())
.then(response => {
if(response.status){
response.data.forEach(bank => {
const option = document.createElement('option');
option.value = bank.iINNo;
option.innerContent = bank.bankName;
});
}
});
<select id="banks"></select>
The issue is because the data you need is in the data property of the data object, so you need to loop over data.data. In addition the properties of each object will be in the second argument of the handler function, code in your example. For example code.bankName.
However it's worth noting that the code can be tidied, and also have its performance improved by using map() to build a single string of option elements which you append to the DOM only once. Try this:
let $dropdown = $('#Bank');
$dropdown.html('<option value="" disabled>Select Bank</option>').val('');
// AJAX commented for example only:
//$.getJSON(url, function(data) {
let data = {
"status": true,
"message": "Request Completed",
"data": [{
"id": 1,
"activeFlag": 1,
"bankName": "Union Bank of India",
"details": "Union Bank of India",
"iINNo": "607161",
"remarks": "",
"timestamp": "21/11/2016 16:00:00"
}, {
"id": 2,
"activeFlag": 1,
"bankName": "Bank of India",
"details": "Bank of India",
"iINNo": "508505",
"remarks": "",
"timestamp": "21/11/2016 16:00:00"
}, ],
"statusCode": 0
}
let html = data.data.map(bank => `<option value="${bank.iINNo}">${bank.bankName}</option>`);
$dropdown.append(html);
//});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="Bank"></select>

Dropdown menus in AngularJS

I have two dropdown menus in my angular app. When I select an option in the 1st dropdown menu, I want that choice to effect the 2nd dropdown menu. Example: 1st menu will have a list of status messages. When I select, let's say, "Need Maintenance" It will change the 2nd menu to the departments relevant to the Maintenance. Or if I choose the status "Lost", it will change the 2nd menu to the departments relevant to the Lost status. Here is my code and setup:
.controller('HomeCtrl', function($scope, $rootScope, $http, $ionicPlatform) {
// This disables the user from being able to go back to the previous view
$ionicPlatform.registerBackButtonAction(function (event) {
event.preventDefault();
}, 100);
// This function only gets called when the submit button is hit on the messaging screen. It posts to server for sending of message
$scope.submit = function() {
$http.post('http://localhost:8000/', {
messageText: $scope.messageText,
name: window.localStorage.getItem("username")
});
$scope.messageText = ""; //clearing the message box
}
})
<div class="form1" ng-controller="HomeCtrl">
<form class="form">
<select placeholder="Select a Subject" ng-model="selectSubject" data-ng-options="option.subject for option in subject"></select>
<select placeholder="Select a Department" ng-model="selectDept" data-ng-options="option.dept for option in dept"></select>
<input type="text" class="messageText" placeholder="Message" ng-model="messageText">
<button class="button" ng-click="submit()"><span>Submit</span></button>
</form>
</div>
That is my controller relevant to the html that is also posted.
I know how to get the information I need from my node server which will be housing the information. All I need help figuring out is changing the options within the 2nd menu when a option is clicked in the 1st menu.
I am thinking just having a http.get call when a option is clicked which will then populate the 2nd menu. The first menu will be static, not changing.
I've just started messing around with Angular and a database and and was able to dynamically populate one select based on the choice in another.
Below is the HTML for my two select boxes (my second select is a multiple, but you can obviously remove that attribute):
<label>Select a Table</label>
<select name="tableDropDown" id="tableDropDown"
ng-options="table.name for table in data.availableTables"
ng-model="data.selectedTable"
ng-change="getTableColumns()">
</select>
<label>Select Columns</label>
<select name="columnMultiple" id="columnMultiple"
ng-options="column.name for column in data.availableColumns"
ng-model="data.selectedColumns"
multiple>
</select>
And I have the controller below. The init function clears all of the data sources for the two select's, retrieves the list of tables (for the first select), sets the selected table to the first table in the list, and then calls the second function.
The second function (which is also called whenever the selected table changes, thanks to the ng-change directive) retrieves the metadata for the selected table and uses it to populate the second select with the list of available columns.
.controller('SimpleController', function($scope, $http) {
init();
function init() {
$scope.data = {
availableTables: [],
availableColumns: [],
selectedTable: {}
};
$http.get("http://some.server.address")
.then(function (response) {
$scope.data.availableTables = response.data.value;
$scope.data.selectedTable = $scope.data.availableTables[0];
$scope.getTableColumns();
});
}
$scope.getTableColumns = function () {
$scope.data.selectedColumns = [];
table = $scope.data.selectedTable.url;
if (table != "") {
$http.get("http://some.server.address/" + table + "/$metadata?#json")
.then(function (response) {
$scope.data.availableColumns = response.data.value;
});
}
}
...
});
maybe you can use the ng-change directive on the 1st select and using the callback function to populate the 2nd select in the way you prefer( http call or local data).
if your Departments objects has a references to the Subject object, something like a subject_id, you can just do a filter:
Example:
<div ng-controller="MyCtrl">
subjects
<select placeholder="Select a Subject" ng-model="selectSubject" ng-options="subject.name for subject in subjects"></select>
departmets
<select placeholder="Select a Department" ng-model="selectDept" ng-options="dept.name for dept in depts | filter:{ subject_id : selectSubject.id }"></select>
</div>
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.subjects = [
{
id: 1,
name: "sub 1",
},
{
id: 2,
name: "sub 2",
}
];
$scope.depts = [
{
id: 1,
name: "Dep 1",
subject_id: 1
},
{
id: 2,
name: "Dep 2",
subject_id: 1
},
{
id: 3,
name: "Dep 3",
subject_id: 2
},
{
id: 4,
name: "Dep 4",
subject_id: 2
}
]
}

AJAX Receive multiple data

I am trying to populate some drop down fields. I have the following dropdown:
Continent
Country
Sport
I want to select first Continent, after that the Country and Sport to populate dynamically. Example:
Europe -> (All Europe countries appear correctly, they are in db).
I choose Algeria; the Sport names should appear on drop down. The json is correct but the ajax, I know, is wrong!
Here is my code:
$(document).ready(function(){
$('#select_continents').on('change', function(){ //continent drop down ID
$('#select_countries').empty();// country drop down ID
$('#select_sport').empty();// sport drop down ID
$.ajax({
method: 'GET',
url: './json.php',
data: { json_continent_country : 1, continent : $('#select_continents').val(), json_country_sport : 1, country : $('#select_countries').val() }
})
.done(function(data){
$.each(JSON.parse(data), function(i, val)
{
$('#select_countries').append('<option value="'+val.id+'">'+val.country_name+'</option>');
$('#select_sport').append('<option value="'+val.id+'">'+val.sport_name+'</option>');
})
})
.fail(function(){
alert('error');
})
})
})
This is what I get:
Any advice?
Why are you reloading the sports list only in case the continent is changed? You are saying that you wish to update the sports list when the country changes, that's not what your code is doing.
Try this instead (omitting any formatting or text elements):
<script type="text/javascript">
$('#continent').on('change', function() {
var continent= $('#continent').val();
// update sport list
$.ajax('./json.php', {
data: {
"continent": continent
}, success: function(data) {
// clear and update sports SELECT
$('#country').html('');
for (var i in data) {
$('#country').append($('<option>').val(data[i].val_id).text(data[i].country_name)
}
}
});
});
$('#country').on('change', function() {
var continent= $('#continent').val();
var country= $('#country').val();
// update sport list
$.ajax('./json.php', {
data: {
"continent": continent, // most likely not relevant, country itself should suffice
"country": country
}, success: function(data) {
// clear and update sports SELECT
$('#sport').html('');
for (var i in data) {
$('#sport').append($('<option>').val(data[i].val_id).text(data[i].sport_name)
}
}
});
});
</script>
<body>
<select id="continent">
<option value="Europe">Europe</option>
</select>
<select id="country">
</select>
<select id="sport">
</select>
</body>
besides, your val.id in your code is the same for country and sport?

best way to bind object array to checkbox in angular with preselected values

i have and list of checkbox. i have read many solutions online but its not getting clear to how to exactly handle this. i have implemented one way but it has multiple problems. one preselected values are not showing and function isSelected is being called multiple times.
HTML -
<div class="checkbox" ng-repeat="service in EditController.services">
<label>
<input type="checkbox" name="{{service.serviceId}}" ng-model="selection"
ng-checked="EditController.isSelected(service.serviceId)"
ng-change="onSelection(selection, service)"/>
<span class="label">{{service.serviceValue}}</span>
</label>
</div>
JS-
onSelection(selection, service){
var EditController = this;
if(!EditController.selectedServices){
EditController.selectedServices = [];
}
if(selection){
EditController.selectedServices.push(service);
}
}
isSelected(serviceId){
var EditController = this;
angular.forEach(EditController.editForm.services, function(value, index){
if(value.serviceId === serviceId){
return true;
}
});
return false;
}
JSON :
editForm :
{
"services": [
{
"serviceId": "ESSL China",
"serviceValue": "ESSL China"
}
}
services :
{
"serviceId": "ESSL China",
"serviceValue": "ESSL China"
},
{
"serviceId": "service1",
"serviceValue": "service1"
}
this doesn't looks good. what could be the best way to handle such scenarios in angularjs world.

knockout.js - nested array data and cascading pre-populated dropdown lists binding

I'm fairly new to knockout.js, however, I've been happily using it in my ASP.NET MVC 4 project, until I ran into this obstacle which has been bothering me for a while, can't seem to put my finger on it.
The scenario which I'm working on requires several combinations of location data (region, country, city), i.e. cascading dropdown lists, which isn't a problem to do when inputting fresh data, but I ran into problem(s) when trying to edit the saved data.
Data is in JSON format, with nested arrays, looks like this (shortened for illustration purposes):
var newData =
[
{
"ID":1,
"Name":"Australia and New Zealand",
"Countries":[
{
"ID":13,
"Name":"Australia",
"Cities":[
{
"ID":19,
"Name":"Brisbane"
},
{
"ID":28,
"Name":"Cairns"
},
...
I suspect I can't load the data (or more clearly, to bind it) properly since I'm having trouble accessing the Region sub-array (which contains Region's Countries) and the Countries sub-array (which contains Countries' Cities).
Then there's the matter of having prepopulated options, which works partially, the viewmodel loads the number of lines, but doesn't select anything.
Here's the VM:
var existingRows = [
{
"Region": 1,
"Country": 13,
"City": 19
},
{
"Region": 1,
"Country": 158,
"City": 3
}];
var Location = function (region, country, city) {
var self = this;
self.region = ko.observable(region);
self.country = ko.observable(country);
self.city = ko.observable(city);
// Whenever the region changes, reset the country selection
self.region.subscribe(function () {
self.country(undefined);
});
// Whenever the country changes, reset the city selection
self.country.subscribe(function () {
self.city(undefined);
});
};
var LocationViewModel = function (data) {
var self = this;
self.lines = ko.observableArray(ko.utils.arrayMap(data, function (row)
{
var rowRegion = ko.utils.arrayFirst(newData, function (region)
{
return region.ID == row.Region;
});
var rowCountry = ko.utils.arrayFirst(rowRegion.Countries, function (country) {
return country.ID == row.Country;
});
var rowCity = ko.utils.arrayFirst(rowCountry.Cities, function (city) {
return city.ID == row.City;
});
return new Location(rowRegion, rowCountry, rowCity);
}));
// Operations
self.addLine = function () {
self.lines.push(new Location())
};
self.removeLine = function (line) {
self.lines.remove(line)
};
};
var lvm = new LocationViewModel(existingRows);
$(function () {
ko.applyBindings(lvm);
});
HTML code:
<tbody data-bind="foreach: lines">
<tr>
<td><select data-bind="options: newData, optionsText: 'Name', optionsValue: 'ID', optionsCaption: 'Select a region...', attr: { name: 'SubRegionIndex' + '['+$index()+']' }, value: region"></select></td>
<td><select data-bind="options: Countries, optionsText: 'Name', optionsValue: 'ID', optionsCaption: 'Select a country...', attr: { name: 'CountryIndex' + '['+$index()+']' }, value: country"></select></td>
<td><select data-bind="options: Cities, optionsText: 'Name', optionsValue: 'ID', optionsCaption: 'Select a city...', attr: { name: 'CityIndex' + '['+$index()+']' }, value: city"></select></td>
<td><a href='#' data-bind='click: $parent.removeLine'>Remove</a></td>
</tr>
</tbody>
I tried to modify the Cart editor example from the knockout.js website with prepopulated data, but haven't really made much progress, I seem to be missing something. Didn't really find anything with nested arrays so I'm stuck here...
I've put up the full code on JSFiddle here:
http://jsfiddle.net/fgXA2/1/
Any help would be appreciated.
The problem is the way in which you are binding to the selected item in your select lists:
<select data-bind="
options: newData,
optionsText: 'Name',
optionsValue: 'ID',
value: region">
</select>
Here you are binding the ID property from your JSON data to the region property on your view model.
This means that when you bind your second select list:
<td data-bind="with: region">
<select data-bind="
options: Countries,
optionsText: 'Name',
optionsValue: 'ID',
value: $parent.country">
</select>
</td>
You attempt to bind to region.Countries. However, region simply contains the selected region ID. In this case the console is your friend:
Uncaught Error: Unable to parse bindings. Message: ReferenceError:
Countries is not defined;
The same problem is true of your third select list for Cities since you are now attempting to bind to country.Cities where country is also just the ID.
There are two options available here. The first is to remove the optionsValue parameters, thus binding the actual JSON objects to your view model properties. That and a binding error on your Cities select box (you were binding to CityName instead of Name) were the only problems:
http://jsfiddle.net/benfosterdev/wHtRZ/
As you can see from the example I've used the ko.toJSON utility to output your view model's object graph. This can be very useful in resolving problems (in your case you would have seen that the region property was just an number).
The downside of the above approach is that you end up storing a copy of all of the countries, and their cities for the selected country in your view model.
A better solution if dealing with large data sets would be to only store the selected identifier (which I believe you were attempting to do originally) and then define computed properties that filter your single data set for the required values.
An example of this can be seen at http://jsfiddle.net/benfosterdev/Bbbt3, using the following computed properties:
var getById = function (items, id) {
return ko.utils.arrayFirst(items, function (item) {
return item.ID === id;
});
};
this.countries = ko.computed(function () {
var region = getById(this.selectedRegion.regions, this.selectedRegion());
return region ? ko.utils.arrayMap(region.Countries, function (item) {
return {
ID: item.ID,
Name: item.Name
};
}) : [];
}, this);
this.cities = ko.computed(function () {
var region = getById(this.selectedRegion.regions, this.selectedRegion());
if (region) {
var country = getById(region.Countries, this.selectedCountry());
if (country) {
return country.Cities;
}
}
}, this);
You can see from the rendered object graph that only the currently selected countries and cities are copied to the view model.

Categories