<optgroup> with JSON on $.each loop - javascript

I’m trying to parse the JSON file in such way that the subsectors of JSON are shown in an <optgroup label=""> (don’t want them to be selectable).
I have this JSON file:
{
"sectors": [
{
"title": "Business, Finance & Technology",
"subsectors": [
{
"title": "Finance and insurance",
"industries": [
{"name": "Retail banking"},
{"name": "Insurance"},
{"name": "Investment banking"}
]
},
{
"title": "Business Services",
"industries": [
{"name": "Accounting & Audit"},
{"name": "Recruitment"},
{"name": "Legal services"}
]
}
]
},
// extra code omitted for brevity
And I populate the <select> options with this:
// populate <select> with available choices
$.getJSON('models/industries.json', function (data) {
$.each(data.sectors, function (i, sector) {
$.each(sector.subsectors, function (i, subsector) {
$('<option />').html('#' + subsector.title).appendTo('.js-industries-select');
$.each(subsector.industries, function (i, industry) {
$('<option />').html(industry.name).appendTo('.js-industries-select');
})
});
});
});
Then I call the Chosen plugin to change the <select> into a dynamic input. You can see which elements I want as label being marked with #.
See demo here: http://jsfiddle.net/qaczD/
I basically need to create an <optgroup> before the last $.each, assign the label="" as subsector.title and then populate that group with the choices. Once the last $.each has finished, close the ` somehow and start a new one.
Any ideas?

Try thisone:
http://jsfiddle.net/qaczD/2/
// populate <select> with available choices
$.getJSON('http://dl.dropboxusercontent.com/u/48552248/websites/timewasted/new/industries.json', function (data) {
$.each(data.sectors, function (i, sector) {
$.each(sector.subsectors, function (i, subsector) {
var optGroup=$('<optgroup />').attr('label','#' + subsector.title).appendTo('.js-industries-select');
$.each(subsector.industries, function (i, industry) {
// if (industry.name.search(regex) != -1) {
$(optGroup).append( $('<option />').html(industry.name));
// }
})
});
});
console.log('yes');
});
// call chosen plugin that prettifies the Industry options
setTimeout(function() {$(".js-industries-select").chosen({
placeholder_text_multiple: 'e.g. Retail banking…'
});}, 1000);

The solution
$.each(sector.subsectors, function (i, subsector) {
var group = $('<optgroup />').attr('label','#' + subsector.title).appendTo('.js-industries-select');
$.each(subsector.industries, function (i, industry) {
$('<option />').html(industry.name).appendTo(group);
})
});

Related

Change select options with other select using JSON data - JQuery

I have a json data which looks like this:
[{
"id": 9,
"category": "Baby",
"items": "[{\"value\":\"Baby Foods\"}]",
"created_at": "2022-01-08T14:28:48.000000Z",
"updated_at": "2022-01-08T14:28:48.000000Z",
"deleted_at": null
},
{
"id": 10,
"category": "Adult",
"items": "[{\"value\":\"Adult Clothes\"},{\"value\":\"Adult Bags\"},{\"value\":\"Adult Shoes\"}]",
"created_at": "2022-01-09T10:46:34.000000Z",
"updated_at": "2022-01-09T10:46:34.000000Z",
"deleted_at": null
}]
It has a list of categories with its items. Now what I am trying to do now is to populate that data on select boxes in a way that if a user change category queried from JSON will show items (as shown on JSON) to another select box as options belonging to that category selected.
Here is what I have tried so far using jquery:
let dropdown = $('#category');
dropdown.empty();
dropdown.append('<option selected="true" disabled>Choose</option>');
dropdown.prop('selectedIndex', 0);
const url = 'http://localhost:8000/admin/categories/show';
// Populate dropdown with list of categories
$.getJSON(url, function (data) {
$.each(data, function (key, entry) {
dropdown.append($('<option></option>').attr('value', entry.category).text(entry.category));
})
});
Here is the result which shows categories on category select box perfectly:
I don't have idea how to get items if certain category is selected on another select box (second one) any help will greatly appreciated.
You can define an eventHandler for your category change event, and whenver it changes, you can read related items from the source data, and put items in the target option, like this:
let data = [{
"category": "Baby",
"items": "[{\"value\":\"Baby Foods\"}]",
},
{
"category": "Adult",
"items": "[{\"value\":\"Adult Clothes\"},{\"value\":\"Adult Bags\"},{\"value\":\"Adult Shoes\"}]",
}
]
let categories = $('#category');
let items = $('#items')
function fillDropdown(target, {data, prop}) {
$.each(data, function(key, data) {
target.append($('<option></option>').attr('value', data[prop]).text(data[prop]));
})
}
fillDropdown(categories, {data, prop: 'category'})
categories.on('change', function(e) {
items.html('');
let value = $(this).val();
if (value) {
let dataItem = data.find(v => v.category == value);
const options = JSON.parse(dataItem.items);
fillDropdown(items, {data: options, prop: 'value'})
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="category">
<option></option>
</select>
<select id="items"></select>

Drop-down empty selection from the menu

I work with a JavaScript app and populate the drop-down menu with a JSON list.
$("#address").append($('<option></option>').attr("value", "1").text(""));
$.each(wallets, function (index, wallet) {
if (selectedCurrency === wallet["currency"].toString().trim()) {
$("#address").append($('<option></option>').attr("value", "1").text(wallet["address"]));
}
})
The UI looks like this,
If I select the empty item (like in the picture), I would like to print empty in the console. Otherwise, I want to print the address value. My intention is to write more code, but, this is where I would like to get started. The code I have,
$("#address").change(function () {
if($(this).val()===""){
console.log('empty');
}
else{
console.log($(this).val());
}
}
However, it only prints 1 in the console and can't distinguish between the empty bar and the address in concern. If I use console.log("The value is " + $(this).text()); inside the change function, it prints every info all together in the console,
The value is mp51mPC38Wtcmybdyd9MPEB2bKnw6eYbCsmqXjM7Mmg6B5LWMad7mHJi339ddaj7xXdBmvXxP1GmXXKojWQJKjgeoASnXVNXCS47z6n41jE2BKKpV6LsPb7dDdStjtuJf1FrYvMMmw1jtrWU5DADxvNR421MKFW1fposgzVMBymnzcZVF4jtZtGAggM5GuLog3Y5o52Mx4xMmq5Rgggfgy2TiRsvtcGm3rxx12R8XbYi9omkdt7ouyJnDXUp4LzdRSRP3ZhU57gUDKy6n2F2QEKk6Fqqk2yMTope5MYp1RtpT949kemrkdfp6qoVN3YiyJhq6nXPvgr3f7YpkS9j
The JSON data I have is something like,
[
{
"id": 1,
"code": "BTC",
"address": "mp51mPC38Wtcmybdyd9MPEB2bKnw6eYbCs",
"currency": "Bitcoin"
},
{
"id": 2,
"code": "BTC",
"address": "mqXjM7Mmg6B5LWMad7mHJi339ddaj7xXdB",
"currency": "Bitcoin"
},
{
"id": 4,
"code": "BTC",
"address": "mvXxP1GmXXKojWQJKjgeoASnXVNXCS47z6",
"currency": "Bitcoin"
}
// some more data
]
What the issue here? My guess is I do something wrong to append the data to the drop-down list and needs to be changed.
I can provide more info if required ....
Just change the value 1 to "" in first option.
$("#address").append($('<option></option>').attr("value", "").text(""));
$.each(wallets, function (index, wallet) {
if (selectedCurrency === wallet["currency"].toString().trim()) {
$("#address").append($('<option></option>').attr("value", "1").text(wallet["address"]));
}
});
check this example.
$("#address").append($('<option></option>').attr("value", "").text(""));
$("#address").append($('<option></option>').attr("value", "1").text("123"));
$("#address").append($('<option></option>').attr("value", "2").text("456"));
$("#address").change(function () {
if($(this).val()===""){
console.log('empty');
}
else{
console.log($(this).val());
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="address">
</select>

Subscribe value on page load

I have two ajax calls. One to load release cycles in first dropdown and another to load scenarios in second dropdown. The scenarios in the second dropdown correspond to the value selected in first dropdown. I am unable to load both on page load. I have to go and select the value by clicking an option in the first dropdown, only then the options in the second dropdown get loaded. How can I achieve this functionality on page load and not by manually selecting or triggering that event.. I do not wish to use ko handlers. Thank you for help in advance.
//load release cycles in first dropdown
self.pushReleaseCycles = function(releaseCycleUrl,scenarioNameUrl1,scenarioNameUrl2){
$.ajax({
url: sharepointScenarioListUrl + releaseCycleUrl,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
var items = data.d.results;
items.forEach( function(item) {
if (self.release_cycles.indexOf(item.Release_x0020_Cycle) == -1) {
self.release_cycles.push(item.Release_x0020_Cycle);
}
});
self.selectedCycle.subscribe(function(value) {
self.scenarios([]);
self.pushScenariosToDropdown(value,scenarioNameUrl1,scenarioNameUrl2);
});
},
error: function (data) {
alert("ERROR in function pushReleaseCycles : " + data);console.log(data);
}
});
};
//load scenarios in second dropdown
self.pushScenariosToDropdown = function(value,scenarioNameUrl1,scenarioNameUrl2){
$.ajax( {
url: sharepointScenarioListUrl + scenarioNameUrl1 + value + scenarioNameUrl2,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
var items = data.d.results;
items.forEach( function(item) {
self.scenarios.push(new ScenarioModel(item));
console.log(data);
});
self.selectedScenario.subscribe(function(value) {
dbName = ko.toJSON(value.title);
jarFile1 = ko.toJSON(value.jar);
fdMimoAvailable = ko.toJSON(value.fdmimo);
self.setValues(dbName,jarFile1,fdMimoAvailable);
});
},
error: function (data) {
alert("ERROR in function pushScenariosToDropdown: " + data);console.log(data);
}
});
};
My HTML:
<select id="dropdown" required class="form-control select2" data-bind="options: release_cycles,value:selectedCycle">
</select>
<select id="dropdown2" required="required" class="form-control select2" data-bind="options: scenarios, optionsText:'scenarioName',optionsCaption:'Please Select Scenario', value:selectedScenario,validationOptions: { errorElementClass:'input-validation-error' },selectedOptions: chosenScenario">
</select>
The way I would handle this is to change how the data is pulled from the server. You will want to include the entire menu structure as needed for the page. In my opinion it's better to have a slightly longer load than a choppy experience. Here's an example of nesting the menus and how that might look.
function ViewModel() {
var self = this;
self.Dropdown1 = ko.observableArray();
self.SelectedItem1 = ko.observable();
self.Dropdown2 = ko.computed(function() {
if (self.SelectedItem1() == null) {
return [];
};
console.log(ko.toJS(self.SelectedItem1()))
return self.SelectedItem1().Submenu;
});
self.SelectedItem2 = ko.observable();
self.LoadDropDown = function() {
self.Dropdown1.push({
"Name": "Hat",
"Value": "top",
"Submenu": [{
"Name": "Blue",
"Value": "#0000FF"
},
{
"Name": "Green",
"Value": "#00FF00"
},
{
"Name": "Red",
"Value": "#FF0000"
}
]
});
self.Dropdown1.push({
"Name": "Shirt",
"Value": "middle",
"Submenu": [{
"Name": "Striped",
"Value": "Striped"
},
{
"Name": "Logo",
"Value": "Logo"
},
{
"Name": "Plain",
"Value": "None"
}
]
});
self.Dropdown1.push({
"Name": "Pants",
"Value": "bottom",
"Submenu": [{
"Name": "Jeans",
"Value": "Jeans"
},
{
"Name": "Kakhis",
"Value": "Kakhis"
},
{
"Name": "Cordroy",
"Value": "Cordroy"
}
]
});
}
self.LoadDropDown();
}
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="options: Dropdown1, optionsText: 'Name', value: SelectedItem1"></select>
<select data-bind="options: Dropdown2, optionsText: 'Name', value: SelectedItem2"></select>
If you don't want to go retrieve the values from the server for the second select box based on the values of the first, but want to load the whole data set, then just load a json object of all of the options for the second box and then parse through that after the first selection. If it's a lot of data though, it's going to impact performance.

jQuery autocomplete suggests all options regardless of input entry

I have a jQuery script that will get a JSON response and create as many "player" objects as there are in the response.
It will then add to availablePlayers which I then use as the variable for the source: field of autocomplete
When a user selects a player name and clicks the "add" button it will, at the moment, just display the guid and name of a player.
However, no matter what letters I type, all the players are given as an option. To illustrate this, if I type "Z" and none of the players have Z in their name, they options are still displayed.
How can I refine this functionality?
HTML
<div class="player-widget">
<label for "players">Players</label>
<input id="player" />
<input id="playerGUID" hidden />
<button id="add">Add</button>
</div>
jQuery
$(document).ready(function(){
var availablePlayers = []; // BLANK ARRAY OF PLAYERS
$("#player").autocomplete({
source: availablePlayers,
response: function (event, ui) {
ui.content = $.map(ui.content, function(value, key) {
return {
label: value.name,
value: value.guid
}
});
},
focus: function(event, ui) {
$("#player").val(ui.item.label);
return false;
},
select: function (event, ui) {
$("#player").val(ui.item.label); // display the selected text
$("#playerGUID").val(ui.item.value); // save selected id to hidden input
return false;
}
});
$.getJSON("http://localhost/Websites/Player-Widgets/service.php", function(data) {
var feedHTML = '';
// LOOP THROUGH EACH PLAYER
$.each(data.players, function(i, player) {
// DEFINE VARIABLES - BASED ON PLAYER ATTRIBUTES
var guid = player.guid;
var name = player.name;
var dob = player.date_of_birth;
var birth = player.birthplace;
var height = player.height;
var weight = player.weight;
var position = player.position;
var honours = player.honours;
// CREATE NEW PLAYER (OBJECT)
var player = {
guid: guid,
name: name,
position: position
};
// ADD TO PLAYER TAG ARRAY
availablePlayers.push(player);
});
console.log("User friendly array");
$.each(availablePlayers, function(i, val) {
console.log(val.guid + " - " + val.name + " [" + val.position + "]");
});
console.log("Array printout");
console.log(JSON.stringify(availablePlayers));
}).done(function(){
console.log("Done! Success!");
$("#player").autocomplete("option", "source", availablePlayers);
});
$("#add").click(function() {
alert($("#playerGUID").val() + " - " + $("#player").val());
});
});
Sample JSON response
{
"players": [
{
"guid": "1",
"name": "Matias Aguero",
"date_of_birth": "1981-02-13",
"birthplace": "San Nicolas, Argentina",
"height": "1.83m (6' 0\")",
"weight": "109kg (17st 2lb)",
"position": "Prop",
"honours": "40 caps"
},
{
"guid": "2",
"name": "George Catchpole",
"date_of_birth": "1994-02-22",
"birthplace": "Norwich, England",
"height": "1.85em (6ft 1\")",
"weight": "104kg (16st 5lb)",
"position": "Centre",
"honours": ""
}
]
}
Your problem is in the source function.
Source function uses request to pass term param to query, and you are ignoring it.
If you're using availablePlayers to query, you should use
source: availablePlayers
and your current function to map {label, text} object in response parameter.
response: function (event, ui) {
ui.content = $.map(ui.content, function(value, key) {
return {
label: value.name,
value: value.guid
}
});
}

Show tree structure data in select box - JQuery, jSon, Ajax

I want to show nested data in either "Ul" and "li" or box but have to show in tree structure.
So in Json, i am receiving folder structure and I don't know how many folders level Json file has. So I have to write my code to pull the data from JSon file and show the data as tree structure based on the levels.
I am also not sure how my JSon file should look like but i came up with this sample JSon file.
So what I need is if some one just point me to the correct direction that for achieve the functionality, what structure of JSon file i need to create and what my Ajax Jquery code should look like
JSON file
{
"folder": [
{
"id":"11"
"name: "test1",
"path": "site/test1",
"children": [
"12",
"13"
]
},
{
"id":"12",
"name":"sub test1",
"path":"site/test1/subtest1",
"children":[
"21"
]
},
{
"id":"13",
"name":"sub test 2",
"path":"site/test1/subtest2",
"children":[]
},
{
"id":"21",
"name":"sub sub test 1",
"path":"site/test1/subtest1/subsubtest1",
"children":[]
},
{
"id":14",
"name":"test2",
"path":"site/test2",
"children":[]
}
]
}
sample JQUERY Code
$.ajax({
dataType: "json",
url: "http://localhost/web/folder.json",
success: function(obj) {
$.each(obj.folder, function (key, value) { // First Level
console.log(value.name);
$.each(value.children, function (k, v) { // The contents inside stars
console.log(v);
});
});
}
});

Categories