Populate multi select select2 option from REST API - javascript

I have 3 select2 fields where I want to populate them using AJAX from API. My question is, how can I populate the first select field option directly from API and then the second field option is populated also by API but based on my selection(s) from the first select field, same goes for the third one.
For example, below are my code & data:
API
[
{
"id": 1,
"project_type": "tv",
"project_stage": "new",
"project_name": "Project A"
},
{
"id": 2,
"project_type": "game",
"project_stage": "completed",
"project_name": "Project B"
},
{
"id": 3,
"project_type": "game",
"project_stage": "new",
"project_name": "Project C"
},
{
"id": 4,
"project_stage": "completed",
"project_type": "film",
"project_name": "Project D"
}
]
HTML
<div class="group">
<select class="project_type" id="project_type" multiple="multiple">
<option value=""></option>
</select>
<select class="project_status" id="project_status" multiple="multiple"">
<option value=""></option>
</select>
<select class="project_select" id="project_select" multiple="multiple">
<option value=""></option>
</select>
</div>
Javascript
$('#project_type').select2({placeholder: "Select project type",});
$('#project_status').select2({placeholder: "Select project Status",});
$('#project_select').select2({placeholder: "Select project",});
Expected Result :
Now the project_type select field wield populate all of the project type as option and say we select "game" then the project_status option would be :
<select class="project_status" id="project_status" multiple="multiple"">
<option value="completed">Completed</option>
<option value="new">New</option>
</select>
and if we select completed, the third filter would be:
<select class="project_select" id="project_select" multiple="multiple">
<option value="Project B">Project B</option>
</select>
I populated this from jinja2 before and its not dynamic, any help is much appreciated thanks.
UPDATE :
below is my current code, for odd reason even for the first filter, its not populating the option even though I'm getting the data :
$('#project_type').select2({
placeholder: "Select project type",
ajax: {
url: '/api/filter/',
delay: 250,
type: 'GET',
data: function (params) {
var query = {
search: params.term,
type: 'public'
}
return query
},
processResults: function (data) {
var data1 = $.map(data, function (obj, idx) {
console.log(obj.project_type);
return obj;
});
console.log("processResults2:", data1);
return {
results: data1,
};
}
}
});

Here is a snippet implementing Select2 Ajax populate (in cascade):
var data = [
{
"id": 1,
"project_type": "tv",
"project_stage": "new",
"project_name": "Project A"
},
{
"id": 2,
"project_type": "game",
"project_stage": "completed",
"project_name": "Project B"
},
{
"id": 3,
"project_type": "game",
"project_stage": "new",
"project_name": "Project C"
},
{
"id": 4,
"project_stage": "completed",
"project_type": "film",
"project_name": "Project D"
}
];
sel_type();
$('#project_status').select2({placeholder: ""});
$('#project_select').select2({ placeholder: ""});
function sel_type() {
$('#project_type').select2({
placeholder: "Select project type",
ajax: {
type: "POST",
url: '/echo/json/',
data: function(params){
var query={
message:params.term,
data: data
}
return { json: JSON.stringify( query ) }
},
processResults: function (data) {
var grouped = groupBy(data.data, 'project_type');
var data1 = [], i = 0;
for (var k in grouped) {
data1.push({"id": i++, "text": k})
}
return {
results: data1,
};
}
}
});
$('#project_type').on('select2:select', function (e) {
var data = e.params.data;
console.log(data);
sel_status(data.text);
});
}
function sel_status(type) {
$('#project_status').select2({
placeholder: "Select project status",
ajax: {
type: "POST",
url: '/echo/json/',
data: function(params){
var query={
message:params.term,
data: data
}
return { json: JSON.stringify( query ) }
},
processResults: function (data) {
var data1 = $.map(data.data, function (obj, idx) {
if (obj.project_type==type)
return obj;
});
var grouped = groupBy(data1, 'project_stage');
var data1 = [], i = 0;
for (var k in grouped) {
data1.push({"id": i++, "text": k})
}
return {
results: data1,
};
}
}
});
$('#project_status').on('select2:select', function (e) {
var data = e.params.data;
console.log(data);
sel_proj(type, data.text);
});
}
function sel_proj(type, status) {
$('#project_select').select2({
placeholder: "Select project",
ajax: {
type: "POST",
url: '/echo/json/',
data: function(params){
var query={
message:params.term,
data: data
}
return { json: JSON.stringify( query ) }
},
processResults: function (data) {
var data1 = $.map(data.data, function (obj, idx) {
if (obj.project_type==type && obj.project_stage==status) {
obj.id = obj.id || idx;
obj.text = obj.project_name;
return obj;
}
});
return {
results: data1,
};
}
}
});
}
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
select {
width:200px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet"/>
<div class="group">
<select class="project_type" id="project_type" multiple="multiple">
<option value=""></option>
</select>
<br/>
<select class="project_status" id="project_status" multiple="multiple">
<option value=""></option>
</select>
<br/>
<select class="project_select" id="project_select" multiple="multiple">
<option value=""></option>
</select>
</div>
but because of the Ajax request it does not work here in StackOverflow.
A working version (using JsFiddle echo) is here: https://jsfiddle.net/beaver71/4nq62nqo/
P.S.: you have to change the uri in Ajax request to yours, and remove POST of data.

Related

How to retain dependent dropdown values using Select2 and Ajax

I have a script that populates the state dropdown based on country id and while everything is working great I can only save the countries dropdown option on page reload but not the state option using html localStorage.
Here is my code:
$(document).ready(function() {
var country_id = null;
var state_id = null;
$('#country').select2();
$('#state').select2();
$('#city').select2();
$('select[name="country"]').on('change', function() {
var country_id = $(this).val();
if (country_id) {
$.ajax({
url: "/world/getStates.php",
type: "GET",
data: {
'country_id': country_id
},
dataType: "json",
success: function(data) {
$('select[name="state"]').empty();
$('select[name="city"]').empty();
$('select[name="state"]').append('<option value="">Select State</option>');
$.each(JSON.parse(data), function(key, value) {
$('select[name="state"]').append('<option value="' + value.id + '">' + value.name + '</option>');
});
}
});
} else {
$('select[name="state"]').empty();
}
});
$('select[name="state"]').on('change', function() {
var country_id = $('#country').val();
var state_id = $(this).val();
if (state_id) {
$.ajax({
url: "/world/getCities.php",
type: "GET",
data: {
'country_id': country_id,
'state_id': state_id
},
dataType: "json",
success: function(data) {
$('select[name="city"]').empty();
$('select[name="city"]').append('<option value="">Select City</option>');
$.each(JSON.parse(data), function(key, value) {
$('select[name="city"]').append('<option value="' + value.id + '">' + value.name + '</option>');
});
}
});
} else {
$('select[name="city"]').empty();
}
});
$('#country').val("value from localStorage").trigger('change');
$('#state').val("value from localStorage").trigger('change');
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>
<label for="country">Country</label>
<select class="csc-select" name="country" id="country">
<option value="">Select Country</option>
<option>Australia</option>
<option>Denmark</option>
<option>Japan</option>
<option>Norway</option>
<option>Switzerland</option>
</select>
<label for="state">State</label>
<select class="csc-select" name="state" id="state">
<option value="">Select State</option>
</select>
<label for="city">City</label>
<select class="csc-select" name="city" id="city">
<option value="">Select City</option>
</select>
So when I call this after the first on change for the country select, it selects the country based on the localStorage value and triggers the change but it does not do the same for the state, any ideas what I am missing here?
Your options inside state dropdown is loaded after the ajax success is executed so your other code doesn't wait for that and .val() fired before only that's the reason the value is not marked as selected inside state dropdown. Now , to fix this you can move that part inside success function of ajax and then call your change event after the options are appended inside state dropdown.
Demo Code :
$(document).ready(function() {
var country_id = 1 //localStorage.getItem("select2CountryValue");
var state_id = 3 //localStorage.getItem("select2StateValue");
var page_load = true; //added this
var data = [{
"id": 1,
"name": "xyz_State1"
}, {
"id": 2,
"name": "xyz_State2"
}, {
"id": 3,
"name": "xyz_State3"
}] //this is just the demo datas
$('#country').select2();
$('#state').select2();
$('select[name="country"]').on('change', function() {
var country_id = $(this).val();
//localStorage.setItem("select2CountryValue", country_id);
if (country_id) {
/*$.ajax({
url: "/world/getStates.php",
type: "GET",
data: {
'country_id': country_id
},
dataType: "json",
success: function(data) {
console.log(data);
$('select[name="city"]').empty();*/
$('select[name="state"]').empty();
$('select[name="state"]').append('<option value="">Select State</option>');
$.each(data, function(key, value) {
$('select[name="state"]').append('<option value="' + value.id + '">' + value.name + '</option>');
});
//check if the change is called on page load
if (page_load == true) {
$('#state').val(state_id).trigger('change'); //assign slected value after elemnt option is added in dom
page_load = false; //add this so that next time this doesn't get execute
}
/* }
});*/
} else {
$('select[name="state"]').empty();
}
});
$('#country').val(country_id).trigger('change');
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" />
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.full.min.js"></script>
<p>
<span>Country</span>
<select class="csc-select" name="country" id="country">
<option value="">Select Country</option>
<option value="1">
xyz
</option>
<option value="2">
xyz2
</option>
</select>
</p>
<p>
<span>State</span>
<select class="csc-select" name="state" id="state">
<option value="">Select State</option>
</select>
</p>
when I call this after the first on change for the country select, it selects the country based on the localStorage value and triggers the change but it does not do the same for the state, any ideas what I am missing here?
When you trigger the change event for your #country list, the list of countries already contains values.
When you trigger the change event for your #state list immediately after that, the list is still empty. There can't be any value selected, so the change event does nothing.
You need to wait until the state list is populated, and then trigger the change event.
// this works immediately, because there are countries in your HTML
$('#country').val("value from localStorage").trigger('change');
// this needs to happen in the `success` callback of country Ajax call
$('#state').val("value from localStorage").trigger('change');
The alternative is that you create a temporary option first:
$('#state').append("temporary <option> created from localStorage");
$('#state').val("value from localStorage").trigger('change');
This way you would not have to wait.
That being said, Select2 supports remote data, you don't have to write the Ajax requests or the <option> creation yourself.
$("#country").select2({
ajax: {
url: "/world/getCountries.php"
},
placeholder: 'Pick a country',
minimumInputLength: 1
}).change(function () {
$("#state").val("").trigger("change");
});
$("#state").select2({
ajax: {
url: "/world/getStates.php",
data: (params) => {
// add selected country ID to URL params
params.country_id = $("#country").val();
return params;
}
},
placeholder: 'Pick a state',
minimumInputLength: 1
});
// initialize selection from previous state...
$("#country").append('<option value="5">Switzerland</option>');
$("#country").val("5");
$("#state").append('<option value="9">Appenzell</option>');
$("#state").val("9");
// server side mock-up -------------------------------------------------
const countries = [
{id: 1, text: 'Australia'},
{id: 2, text: 'Denmark' },
{id: 3, text: 'Japan'},
{id: 4, text: 'Norway'},
{id: 5, text: 'Switzerland'}
];
const states = [
{id: 1, text: 'New South Wales', country_id: 1},
{id: 2, text: 'Victoria', country_id: 1},
{id: 3, text: 'Hovedstaden', country_id: 2},
{id: 4, text: 'Midtjylland', country_id: 2},
{id: 5, text: 'Hokkaido', country_id: 3},
{id: 6, text: 'Shikoku', country_id: 3},
{id: 7, text: 'Northern Norway', country_id: 4},
{id: 8, text: 'Southern Norway', country_id: 4},
{id: 9, text: 'Appenzell', country_id: 5},
{id: 10, text: 'Zürich', country_id: 5},
];
$.mockjaxSettings.logging = 1;
$.mockjax({
url: "/world/getCountries.php",
contentType: "application/json",
response: function(settings) {
this.responseText = {
results: countries.filter(item =>
!settings.data.term || item.text.toLowerCase().includes(settings.data.term.toLowerCase())
)
};
}
});
$.mockjax({
url: "/world/getStates.php",
contentType: "application/json",
response: function(settings) {
console.log(settings.data);
this.responseText = {
results: states.filter(item =>
item.country_id == settings.data.country_id && (
!settings.data.term || item.text.toLowerCase().includes(settings.data.term.toLowerCase())
)
)
};
}
});
select {
width: 200px;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mockjax/2.6.0/jquery.mockjax.min.js"></script>
<select id="country"></select>
<select id="state"></select>

Sort API results alphabetically in dropdown element (Javascript Only Please)

I have two dropdown elements below that are populated with data from the result array.
I simply want to sort each option coming from the result array alphabetically in the drop-down elements.
Would also like to mention that in my dev environment the result data is actually coming from an API.
Thanks in advance!
let result = [{
name: "B name",
tag: "B tag",
price: "50"
},
{
name: "C name1",
tag: "C tag",
price: "10"
},
{
name: "A name",
tag: "A tag",
price: "20"
},
{
name: "E name",
tag: "E tag",
price: "30"
},
{
name: "D name",
tag: "D tag",
price: "40"
}
];
//Generic function to fill a dropdown with options
let populateDropDown = (params) => {
let set = new Set()
params.optionsToPopulate.forEach(item => {
const txt = item[params.text];
if (!set.has(txt)) {
params.element.add(new Option(txt, txt))
set.add(txt);
}
})
}
//Initialize tags dropdown
(function() {
document.getElementById("tags").addEventListener('change', (event) => {
tagChanged(event);
});
let params = {
optionsToPopulate: result,
element: document.getElementById("tags"),
id: "tag",
text: "tag"
}
populateDropDown(params);
})();
//Tags dropdown change event.
let tagChanged = (event) => {
let tagValue = event.target.value;
//filter the results based on the value of tags dropdown
let optionsToAdd = result.filter(item => item.tag === tagValue);
let names = document.getElementById("names");
names.options.length = 1;
let params = {
optionsToPopulate: optionsToAdd,
element: names,
id: "name",
text: "name"
}
populateDropDown(params);
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
Tags:
<select id="tags">
<option value="please select">please select</option>
</select>
<br><br><br> Names:
<select id="names">
<option value="please select">please select</option>
</select>
</body>
</html>
let result = [{
name: "B name",
tag: "B tag",
price: "50"
},
{
name: "C name1",
tag: "C tag",
price: "10"
},
{
name: "A name",
tag: "A tag",
price: "20"
},
{
name: "E name",
tag: "E tag",
price: "30"
},
{
name: "D name",
tag: "D tag",
price: "40"
}
];
// Sort Alphabetically
var sortedResult = result.sort(function (a, b) {
var tagA = a.tag.toLowerCase();
var tagB = b.tag.toLowerCase();
if (tagA < tagB)
return -1;
else if (tagA > tagB)
return 1;
});
//Generic function to fill a dropdown with options
let populateDropDown = (params) => {
let set = new Set()
params.optionsToPopulate.forEach(item => {
const txt = item[params.text];
if (!set.has(txt)) {
params.element.add(new Option(txt, txt))
set.add(txt);
}
})
}
//Initialize tags dropdown
(function () {
document.getElementById("tags").addEventListener('change', (event) => {
tagChanged(event);
});
let params = {
optionsToPopulate: sortedResult,
element: document.getElementById("tags"),
id: "tag",
text: "tag"
}
populateDropDown(params);
})();
//Tags dropdown change event.
let tagChanged = (event) => {
let tagValue = event.target.value;
//filter the results based on the value of tags dropdown
let optionsToAdd = sortedResult.filter(item => item.tag === tagValue);
let names = document.getElementById("names");
names.options.length = 1;
let params = {
optionsToPopulate: optionsToAdd,
element: names,
id: "name",
text: "name"
}
populateDropDown(params);
}
Tags:
<select id="tags">
<option value="please select">please select</option>
</select>
<br><br><br> Names:
<select id="names">
<option value="please select">please select</option>
</select>
Try like this
-Just add sort function before populateDropDown().
-this will sort result by name key value in ascending order.
result = result.sort((a, b) => (a['name'] > b['name']) ? 1 : ((b['name'] > a['name']) ? -1 : 0));
-result will look like this
Sort the array
SO - sort-array-of-objects-by-string-property-value
let result = [{
name: "B name",
tag: "B tag",
price: "50"
},
{
name: "C name1",
tag: "C tag",
price: "10"
},
{
name: "A name",
tag: "A tag",
price: "20"
},
{
name: "E name",
tag: "E tag",
price: "30"
},
{
name: "D name",
tag: "D tag",
price: "40"
}
];
result.sort(compare)
//Generic function to fill a dropdown with options
let populateDropDown = (params) => {
let set = new Set()
params.optionsToPopulate.forEach(item => {
const txt = item[params.text];
if (!set.has(txt)) {
params.element.add(new Option(txt, txt))
set.add(txt);
}
})
}
//Initialize tags dropdown
(function() {
document.getElementById("tags").addEventListener('change', (event) => {
tagChanged(event);
});
let params = {
optionsToPopulate: result,
element: document.getElementById("tags"),
id: "tag",
text: "tag"
}
populateDropDown(params);
})();
//Tags dropdown change event.
let tagChanged = (event) => {
let tagValue = event.target.value;
//filter the results based on the value of tags dropdown
let optionsToAdd = result.filter(item => item.tag === tagValue);
let names = document.getElementById("names");
names.options.length = 1;
let params = {
optionsToPopulate: optionsToAdd,
element: names,
id: "name",
text: "name"
}
populateDropDown(params);
}
function compare( a, b ) {
if ( a.tag < b.tag ){
return -1;
}
if ( a.tag > b.tag ){
return 1;
}
return 0;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
Tags:
<select id="tags">
<option value="please select">please select</option>
</select>
<br><br><br> Names:
<select id="names">
<option value="please select">please select</option>
</select>
</body>
</html>

unable to filter array of objects in Vue js

I want to filter the games by genre. pdList is the array of objects(games).To do this i'm using Array.filter().
but its not working. below is the code. Correct me if my approach is wrong. its not giving any error also in the console.
Vuejs code:
new Vue({
el: "#app",
data: {
currentFilter:"all",
pdList:[,
{
"title": "Double Dragon: Neon",
"url": "/games/double-dragon-neon/xbox-360-131320",
"platform": "Xbox 360",
"score": 3,
"genre": "Fighting",
"editors_choice": "N",
"release_year": 2012
},
{
"title": "Guild Wars 2",
"url": "/games/guild-wars-2/pc-896298",
"platform": "PC",
"score": 9,
"genre": "RPG",
"editors_choice": "Y",
"release_year": 2012
}]
},
methods: {
filterByGenre:function(filterby){
this.currentFilter = filterby;
},
filteredGames:function(pdList){
console.log("inside filtergames");
if(this.currentFilter == "all"){
return pdList;
}else{
return pdList.filter(function(game){
console.log(this.currentFilter);
return game.genre == this.currentFilter;
});
}
}
}
})
HTML
<div id="app">
<h2>Game Lister:</h2>
<ol>
<li v-for="game in filteredGames(pdList)">
{{game.genre}}
</li>
</ol>
</div>
<select v-model="currentFilter">
<option value="all">all</option>
<option value="Platformer">Platformer</option>
<option value="Platformer">Puzzle</option>
<option value="Platformer">Sports</option>
<option value="Platformer">Strategy</option>
</select>
The idea isn't a correct one. Some flaws in the code:
In Template:
Select option is out of div#app - will result select in not being shown
All options but 'all' have same value in select
In ViewModel:
pdList in data() has started with [, - which will break the code
A simple computed function will do it all - and you haven't used any of the methods you used in your template
The solution would be:
Template
<div id="app">
<h2>Game Lister:</h2>
<ol>
<li v-for="game in filteredGames">{{game.title}}</li>
</ol>
<select v-model="currentFilter">
<option value="all">all</option>
<option value="Fighting">Fighting</option>
<option value="RPG">RPG</option>
</select>
</div>
ViewModel
data: {
currentFilter: "all",
pdList: [{
"title": "Double Dragon: Neon",
"url": "/games/double-dragon-neon/xbox-360-131320",
"platform": "Xbox 360",
"score": 3,
"genre": "Fighting",
"editors_choice": "N",
"release_year": 2012
}, {
"title": "Guild Wars 2",
"url": "/games/guild-wars-2/pc-896298",
"platform": "PC",
"score": 9,
"genre": "RPG",
"editors_choice": "Y",
"release_year": 2012
}]
},
computed: {
filteredGames () {
const self = this;
if (self.currentFilter === 'all') {
return self.pdList;
} else {
return self.pdList.filter(function(game) {
return self.currentFilter === game.genre;
});
}
}
}
A method invocation will always run the function whenever a rerender happens. To know that it depends on this.pdList, you don't need to parse it in.
HTML
<li v-for="game in filteredGames()">
{{game.genre}}
</li>
Vuejs
filteredGames:function(){
console.log("inside filtergames");
if(this.currentFilter == "all"){
return this.pdList;
} else {
return this.pdList.filter(function(game){
console.log(this.currentFilter);
return game.genre == this.currentFilter;
});
}
}
You can try this approach as well after correcting the syntax issues as mentioned by #Naiful.
Template :
<div id="app">
<h2>Game Lister:</h2>
<ol>
<li v-for="game in filteredGames">
{{game.genre}}
</li>
</ol>
<select v-model="currentFilter">
<option value="all">all</option>
<option value="Platformer">Platformer</option>
<option value="Platformer">Puzzle</option>
<option value="Platformer">Sports</option>
<option value="Platformer">Strategy</option>
</select>
</div>
You can then put a watch on your currentFilter model and invoke your filterByGenre function to update filteredGames.
VueJs Code :
new Vue({
el: "#app",
data (){
return {
currentFilter:"all",
filteredGames : [],
pdList:[{
"title": "Double Dragon: Neon",
"url": "/games/double-dragon-neon/xbox-360-131320",
"platform": "Xbox 360",
"score": 3,
"genre": "Fighting",
"editors_choice": "N",
"release_year": 2012
},
{
"title": "Guild Wars 2",
"url": "/games/guild-wars-2/pc-896298",
"platform": "PC",
"score": 9,
"genre": "RPG",
"editors_choice": "Y",
"release_year": 2012
}]
}
},
created (){
this.filterByGenre();
},
watch : {
'currentFilter' (){
this.filterByGenre();
}
},
methods: {
filterByGenre (){
this.filteredGames = [];
if(this.currentFilter == "all"){
this.filteredGames = this.filteredGames.concat(this.pdList);
}else{
this.filteredGames = this.pdList.filter(game => game.genre == this.currentFilter);
}
}
}
});
P.S. - In your vue code, data should be a function which returns an object like recommended in VueJS official documentation.
added the search feature also.
filteredGames () {
const self = this;
//for searching
if(this.search.length > 0){
return self.pdList.filter(function(game) {
console.log(game.title)
return game.title.toLowerCase().indexOf(self.search.toLowerCase()) >= 0;
});
}else{
if (self.currentFilter === 'all') {
return self.pdList;
} else {
return self.pdList.filter(function(game) {
return self.currentFilter === game.genre;
});
}
}
}

I want to get my value from json data

i have json like this
{
"id":"1",
"name":"Kitchen Set",
"parent_id":"0",
},
{
"id":"2",
"name":"Bedroom",
"parent_id":"0"
},
{
"id":"3",
"name":"Living Room",
"parent_id":"0"
},
{
"id":"4",
"name":"Kitchen Set",
"parent_id":"1",
"price":"1000"
},
{
"id":"5",
"name":"Meja Bar",
"parent_id":"1",
"price":"2000"
},
and i want to add price: to my javascript
here is my question i want to get the price from my json to my javascript how can i do that??
i try this but it doesnt work
load_json_data('Price');
function load_json_data(price)
{
var html_code = '';
$.getJSON('int_fur_fin.json', function(data)
}
and this is my javascript
<script>
$(document).ready(function(){
load_json_data('Interior');
function load_json_data(id, parent_id)
{
var html_code = '';
$.getJSON('int_fur_fin.json', function(data){
html_code += '<option value="">Select '+id+'</option>';
$.each(data, function(key, value){
if(id == 'Interior')
{
if(value.parent_id == '0')
{
html_code += '<option value="'+value.id+'">'+value.name+'</option>';
}
}
else
{
if(value.parent_id == parent_id)
{
html_code += '<option value="'+value.id+'">'+value.name+'</option>';
}
}
});
$('#'+id).html(html_code);
});
}
$(document).on('change', '#Interior', function(){
var Interior_id = $(this).val();
if(Interior_id != '')
{
load_json_data('Furniture', Interior_id);
}
else
{
$('#Furniture').html('<option value="">Select Furniture</option>');
}
});
});
</script>
i use this javascript code to populate my dropdown
<form>
<select name="Interior Details" id="Interior" class="form-control input-lg">
<option value="">Select Interior Details</option>
</select>
<br />
<select name="Furniture" id="Furniture" class="form-control input-lg" required >
<option value="">Select Furniture</option>
</select>
</form>
You can use array.find() method to find the matching element. Also i have modified your JSON as a array.
items.find(t=>t.parent_id ==='1');
DEMO
var items = [{
"id":"1",
"name":"Kitchen Set",
"parent_id":"0",
},
{
"id":"2",
"name":"Bedroom",
"parent_id":"0"
},
{
"id":"3",
"name":"Living Room",
"parent_id":"0"
},
{
"id":"4",
"name":"Kitchen Set",
"parent_id":"1",
"price":"1000"
},
{
"id":"5",
"name":"Meja Bar",
"parent_id":"1",
"price":"2000"
}];
var result = items.find(t=>t.parent_id ==='1');
console.log(result);
EDIT
If you want multiple elements with matching id use array.filter.
var items = [{
"id":"1",
"name":"Kitchen Set",
"parent_id":"0",
},
{
"id":"2",
"name":"Bedroom",
"parent_id":"0"
},
{
"id":"3",
"name":"Living Room",
"parent_id":"0"
},
{
"id":"4",
"name":"Kitchen Set",
"parent_id":"1",
"price":"1000"
},
{
"id":"5",
"name":"Meja Bar",
"parent_id":"1",
"price":"2000"
}];
var result = items.filter(t=>t.parent_id ==='1');
console.log(result);

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.

Categories