Looping over JSON nested array in JavaScript - javascript

I have an API which give me a JSON file like this :
(I edited my post.i hope it can help)
{
"events": {
"Israel Liga Bet South": [
{
"id": 47,
"league_name": "Israel Liga Bet South",
"home_team": "Otzma FC Holon",
"away_team": "Beitar Ramat Gan"
}
],
"Israel Liga Bet North": [
{
"id": 46,
"league_name": "Israel Liga Bet North",
"home_team": "Bnei HaGolan VeHaGalil",
"away_team": "Maccabi Maalot Tarshiha"
}
],
"India Bangalore Super Division": [
{
"id": 40,
"league_name": "India Bangalore Super Division",
"home_team": "ASC",
"away_team": "South United"
}
]
}
}
i wrote this code :
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
var events;
events = myObj.events;
Object.keys(events).forEach(function (key) {
var inPlayEvents = events[key];
inPlayEvents.forEach(element => {
var div = document.createElement('div');
div.innerHTML = "my html codes";
div.setAttribute('class', 'event-type');
document.body.appendChild(div);
});
});
}
};
xmlhttp.open("GET", "json.txt", true);
xmlhttp.send();
but it showing me all of the matches
I want to show the same league matches in the same <div>
how can I do it?
thanks for your help

First, your JSON is wrongly formatted and it wouldn't even parse. Assuming the JSON object is like this:
"Categories": {
"cat1": [
{
"id": 1,
"Category_name": "cat1",
"Name": "iphone6",
"Details": "packed",
}
],
"cat2": [
{
"id": 2,
"Category_name": "cat2",
"Name": "GalaxyS10",
"Details": "stock"
}
],
"cat1": [
{
"id": 3,
"Category_name": "cat1",
"Name": "iphone5s",
"Details": "stock"
}
]
}
As for but it showing me all of the products I want to show the same category products in the same div you need to change the following in your iterator code:
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
var Categories;
Categories = myObj.Categories;
Object.keys(Categories).forEach(function(key) {
var Products = Categories[key];
// create your div here
var div = document.createElement('div');
div.innerHTML = '';
Products.forEach(element => {
//[! remove this] var div = document.createElement('div');
//[! concatenate instead of assigning it] div.innerHTML = "html codes here";
div.innerHTML += 'your html here';
div.setAttribute('class', 'category-type');
Why? Because in your code you are reassigning the HTML to a new div for every product. Since you want to display all the information for all products under each category in a single div, your code would not work as expected.

Related

How to filter an objects where is employeeId equals to some value

I'm using knockoutjs, but the question is really in Javascript domain.
I have variable vm.filteredSerivces() which contains all services by all employees.
Now, I want to just preserve those filteredSerivces where is vm.filteredSerivces()[0].GroupedServices[x].EmployeeId == 3684 (x is the number of index number of each object in GroupedServices object list)
I tried as follows:
var filteredSrvcs = vm.filteredSerivces()[0].GroupedServices.filter(x => x.EmployeeId != Id).remove();
vm.filteredSerivces(filteredSrvcs );
But I changed structure in that way, and my bindings in html is not corresponding.
Is there any other way to just remove this sub-sub object, and to preserve a structure as it is?
Here is the
Here's an example that maps a new array of new objects and the filter is set to only include the GroupedServices items where Id == 2000
let res = data.map(({ServiceTypeName, GroupedServices}) =>{
GroupedServices= GroupedServices.filter(({Id}) => Id == 2000);
return {ServiceTypeName,GroupedServices }
})
console.log(res)
<script>
let data =
[
{
"ServiceTypeName": "Type 1",
"GroupedServices": [{
"Id": 1,
"Name": "A"
}, {
"Id": 2,
"Name": "A"
},
{
"Id": 28456,
"Name": "AGSADGJS"
}]
},
{
"ServiceTypeName": "Type 2",
"GroupedServices": [{
"Id": 1203,
"Name": "AHASJ"
}, {
"Id": 2000,
"Name": "AHSJD"
},
{
"Id": 284536,
"Name": "UEHNCK"
}]
}];
</script>

How can I remove completed tasks in toDo App Javascript

I don't have idea how can i deleted all completed tasks from my json file and my app view:
json:
{
"list": [
{
"name": "Cleaning",
"desc": "by me",
"date": "11-3-2018 13:38",
"active": "false",
"id": 1
},
{
"name": "Wash the dishes",
"desc": "by me",
"date": "11-3-2018 23:11",
"active": "true",
"id": 2
},
{
"name": "Training",
"desc": "go with bro",
"date": "15-1-2016 23:41",
"active": "false",
"id": 3
}
]
}
I would like to deleted all tasks - active: false by one click button.
I have to use XMLHttpRequest.
You can loop through your JSON variable then have a condition on checking the active key. If its true then remove it. You can use splice to remove elements from an array. Then send it to your server side or etc.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
You will need to go server side to change the content of files, which I think you want to do.
Using JS and PHP you would get something like:
For the JS:
$("#yourButtonId").on('click', function(){
//Get the JSON file
var request = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var jsonObj = JSON.parse(this.responseText);
//Go over all tasks and remove if active is set to false
for (var i = 0; i < jsonObj.length; i++) {
if(jsonObj.list[i].active == "false"){
delete jsonObj.list[i];
};
}
//Send the updated json file as string to PHP
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "yourphpfile.php");
xmlhttp.send(JSON.stringify(jsonObj));
}
}
request.open("GET", "urlToJson.json", false);
request.setRequestHeader("Content-type", "application/json")
request.send(null);
});
For the PHP:
//Get your updated json string
$theJson = $GET['jsonObj'];
//Write the updated json string to the file
$myfile = fopen("urlToJson.json", "w") or die("Unable to open file!");
fwrite($myfile, json_encode($theJson));
fclose($myfile);
Try this :
var jsonObj = {
"list": [{
"name": "Cleaning",
"desc": "by me",
"date": "11-3-2018 13:38",
"active": "false",
"id": 1
},
{
"name": "Wash the dishes",
"desc": "by me",
"date": "11-3-2018 23:11",
"active": "true",
"id": 2
},
{
"name": "Training",
"desc": "go with bro",
"date": "15-1-2016 23:41",
"active": "false",
"id": 3
}
]
};
function removeCompletedTask() {
var resJson = jsonObj.list.filter(item => item.active == "true");
console.log(resJson);
}
<input type="button" value="Remove" onClick="removeCompletedTask()"/>
I use only json server (without php file)
If I want to delete single task I do this code
function deleteTask(task) {
var xhr = new XMLHttpRequest();
xhr.open("DELETE", url + "/" + task.dataset.id, true);
xhr.onload = function() {
var json = JSON.parse(xhr.responseText)
if (xhr.readyState == 4 && xhr.status == 200) {
task.parentNode.parentNode.removeChild(task.parentNode);
}
}
xhr.send(null);
}
I did checkbox to change active my tasks and i would like to delete all of them i try something like this:
function clearTasksCompleted(task) {
var taskCompleted = task.parentElement.parentElement.querySelectorAll('li');
var completed = [];
for(let i =0; i<taskCompleted.length; i++){
if(taskCompleted[i].querySelector('.checkbox').checked)
{
completed.push(taskCompleted[i]);
}
}
for (let i=0; i<completed.length; i++) {
var xhr = new XMLHttpRequest();
xhr.open("DELETE", url + "/" + completed[i].dataset.id, true);
xhr.onload = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var json = JSON.parse(xhr.responseText);
completed[i].parentNode.removeChild(completed[i])
}
}
xhr.send(null);}}
`
and this deleted tasks from json but dont render my page automatically, only after preload i don't see completed tasks

filter result using 2 JSON

This is my saved localstorage,
[{"industry_Id":1,"merchant_id":2}]
I want to filter below result, to get HP.
{
"industries": [
{
"id": 1,
"name": "oil and gas",
"merchant": [
{
"id": 1,
"name": "ABC",
},
{
"id": 2,
"name": "DEF",
},
{
"id": 3,
"name": "GHJ",
}
]
},
{
"id": 2,
"name": "IT",
"merchant": [
{
"id": 1,
"name": "Apple",
},
{
"id": 2,
"name": "HP",
},
{
"id": 3,
"name": "Google",
}
]
}
]
}
I thought of using multiple $.each but it have to iterate few times and it's quite redundant.
I would prefer using Javascript for loop, that way you can skip iterating over every object once required element is found.
Without jQuery (using for)
var i, j, merchant = null;
for(i = 0; i < data['industries'].length; i++){
if(data['industries'][i]['id'] == arg[0]['industry_Id']){
for(j = 0; j < data['industries'][i]['merchant'].length; j++){
if(data['industries'][i]['merchant'][j]['id'] == arg[0]['merchant_id']){
merchant = data['industries'][i]['merchant'][j];
break;
}
}
if(merchant !== null){ break; }
}
}
With jQuery (using $.each)
var merchant_found = null;
$.each(data['industries'], function(i, industry){
if(industry['id'] == arg[0]['industry_Id']){
$.each(industry['merchant'], function(i, merchant){
if(merchant['id'] == arg[0]['merchant_id']){
merchant_found = merchant;
}
return (!merchant_found);
});
}
return (!merchant_found);
});
var arg = [{"industry_Id":1,"merchant_id":2}];
var data = {
"industries": [
{
"id": 1,
"name": "oil and gas",
"merchant": [
{
"id": 1,
"name": "ABC",
},
{
"id": 2,
"name": "DEF",
},
{
"id": 3,
"name": "GHJ",
}
]
},
{
"id": 2,
"name": "IT",
"merchant": [
{
"id": 1,
"name": "Apple",
},
{
"id": 2,
"name": "HP",
},
{
"id": 3,
"name": "Google",
}
]
}
]
};
var i, j, merchant = null;
for(i = 0; i < data['industries'].length; i++){
if(data['industries'][i]['id'] == arg[0]['industry_Id']){
for(j = 0; j < data['industries'][i]['merchant'].length; j++){
if(data['industries'][i]['merchant'][j]['id'] == arg[0]['merchant_id']){
merchant = data['industries'][i]['merchant'][j];
break;
}
}
if(merchant !== null){ break; }
}
}
console.log(merchant);
document.writeln("<b>Without jQuery:</b><br>");
document.writeln((merchant !== null) ? "Found " + merchant['name'] : "Not found");
var merchant_found = null;
$.each(data['industries'], function(i, industry){
if(industry['id'] == arg[0]['industry_Id']){
$.each(industry['merchant'], function(i, merchant){
if(merchant['id'] == arg[0]['merchant_id']){
merchant_found = merchant;
}
return (!merchant_found);
});
}
return (!merchant_found);
});
console.log(merchant_found);
document.writeln("<br><br><b>With jQuery:</b><br>");
document.writeln((merchant_found) ? "Found " + merchant_found['name'] : "Not found");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
selectors.map(function(selector) {
return data.industries.filter(function(industry) {
return industry.id == selector.industry_Id;
})[0].merchant.filter(function(merchant) {
return merchant.id == selector.merchant_id;
})[0].name;
});
// => DEF
If you want "HP", you want industry 2, not industry 1.
.filter(...)[0] is not really optimal. You could use .find(...), but that is not yet universally supported. Or you could use plain old JavaScript and write for loops instead to make it fast. Or you could use objects with ID keys instead of arrays to make lookups faster.
When it comes into a position where collection of data is what you're processing, I suggest you to take a look at underscore.js. It's not optimal choice for the best performance but it does make you code more readable and makes more sense especially when compared with loop.
Say data is a variable which stores your JSON data.
Try this:
// Given this selector criteria
var select = [{"industry_Id":1,"merchant_id":2}];
function filterByCriteria(criteria, data){
var match = [];
_.each(criteria, function(crit){
function matchIndustry(rec){ return rec.id===crit.industry_Id }
function matchMerchant(rec){ return rec.id===crit.merchant_id }
// Filter by industry id
var industry = _.first(_.where(data.industry, matchIndustry));
// Filter by merchant id
var merchant = _.where(industry.merchant, matchMerchant);
_.each(merchant, function addToMatchResult(m){
match.push(m.name);
});
});
return match;
}
var filteredData = filterByCriteria(select, data);
From snippet above, any merchants which match the search criteria will be taken to the match list. Is it more readable to you?
Do you even need numerical id's? Gets super easy when you don't.
/*
{
"industry": {
"oil and gas":{
"merchant": {
"ABC": {
"name": "ABC oil"
},
"DEF": {
"name": "DEF gas"
},
"GHJ" :{
"name": "GHJ oil and gas"
}
}
},
"IT": {
"merchant": {
"Apple" : {
"name": "Apple computers"
},
"HP": {
"name": "Hewlett Packard"
},
"Google": {
"name": "Google. Maw haw haw"
}
}
}
}
}
*/
var data = '{"industry": {"oil and gas":{"merchant": {"ABC": {"name": "ABC oil"},"DEF": {"name": "DEF gas"},"GHJ" :{"name": "GHJ oil and gas"}}},"IT": {"merchant": {"Apple" : {"name": "Apple computers"},"HP": {"name": "Hewlett Packard"},"Google": {"name": "Google. Maw haw haw"}}}}}';
data = JSON.parse(data);
var merchant = data.industry['IT'].merchant['HP'];
alert(merchant.name);
//console.log(merchant.name);

how to create elements dynamically in HTML using JSON file

I want to create HTML elements dynamically using JSON file.
{"myObject": {
"JAVA": {
"id": "JAVAsubj",
"path": "json/data.json"
},
"C#": {
"id": "JAVAsubj",
"path": "json/data1.json"
},
"C++": {
"id": "JAVAsubj",
"path": "json/data2.json"
}
}
}
This is my JSON file. i want to create HTML buttons dynamically. Buttons should be create like JAVA,C#,C++. if i add something next to C++ then that button should get created dynamically
You can try something like this FIDDLE
however, i changed the myObject to an array of json objects as follows:
var jsonObj = {"myObject":
[
{
title: 'JAVA',
id: "JAVAsubj",
path: "json/data.json"
},
{
title: "C#",
id: "JAVAsubj",
path: "json/data1.json"
},
{
title: "C++",
id: "JAVAsubj",
path: "json/data2.json"
}
]
}
var count = Object.keys(jsonObj.myObject).length;
var container= document.getElementById('buttons'); // reference to containing elm
for(var i=0;i<count;i++){
var obj= jsonObj.myObject[i];
var button = "<input type='button' value="+obj.title+"></input>"
container.innerHTML+=button;
}
First thing you need to do that get your JSON into js object :
var myJSON= {"myObject": {
"JAVA": {
"id": "JAVAsubj",
"path": "json/data.json"
},
"C#": {
"id": "JAVAsubj",
"path": "json/data1.json"
},
"C++": {
"id": "JAVAsubj",
"path": "json/data2.json"
}
}
}
now get the value of your object into dictionary like below :
var dctLanguages = myJSON["myObject"];
now to render buttons dynamically, just do this :
var strHTML = '';
for (var key in dctLanguages)
{
var language = dctLanguages[key];
strHTML += '<input type="button" id="'+language.id+'" value="'+key+'"/>';
}
and append this HTML into your container div as follows :
$(strHTML).appendTo("#container");
Hope this will work for you..
const info = [
{
"id": 1,
"img": "a.jpg",
"name": "Avinash Mehta",
"desc": "I am Web Developer"
},
{
"id": 2,
"img": "c.jpg",
"name": "Avinash",
"desc": "I am Web"
},
{
"id": 3,
"img": "b.jpg",
"name": "Mehta",
"desc": "I am Developer"
},
]
const main = document.querySelector(".main");
window.addEventListener("DOMContentLoaded", function(){
let displayInfo = info.map(function(profile){
return` <div class="profile">
<img src="${profile.img}" alt="">
<h2>${profile.name}</h2>
<p>${profile.desc}</p>
</div>`
});
displayInfo = displayInfo.join("");
main.innerHTML = displayInfo
})
This shoule help you
const info = [
{
"id": 1,
"img": "a.jpg",
"name": "Avinash Mehta",
"desc": "I am Web Developer"
},
{
"id": 2,
"img": "c.jpg",
"name": "Avinash",
"desc": "I am Web"
},
{
"id": 3,
"img": "b.jpg",
"name": "Mehta",
"desc": "I am Developer"
},
]
const main = document.querySelector(".main");
window.addEventListener("DOMContentLoaded", function(){
let displayInfo = info.map(function(profile){
return` <div class="profile">
<img src="${profile.img}" alt="">
<h2>${profile.name}</h2>
<p>${profile.desc}</p>
</div>`
});
displayInfo = displayInfo.join("");
main.innerHTML = displayInfo
})

XUL. Tree.Why sub-items drops?

I have a XUL tree, which will contain some dynamic JSON tree.
I Have JSON(Generated by my Win app):
{
"Description": "",
"id": "0x7183D2AD",
"Name": "",
"Children": [{
"Description": "",
"id": "0x660452D5",
"Name": "Bookmarks menu",
"Children": [{
"Description": "",
"id": "0x32DD7955",
"Name": "Mozilla Firefox",
"Children": []
}]
},
{
"Description": "",
"id": "0x10EFAAFD",
"Name": "Bookmarks panel",
"Children": [{
"Description": "",
"id": "0x2542B587",
"Name": "123",
"Children": []
}]
},
{
"Description": "",
"id": "0x39AD4290",
"Name": "Tags",
"Children": []
},
{
"Description": "",
"id": "0x464248E7",
"Name": "unassigned bookmarks",
"Children": []
}]
I want fill the XUL tree by this data & realize structure(for example: this JSON ^^):
Bookmarks menu
Mozilla Firefox
Bookmarks panel
123
Tags
Unassigned bookmarks
I wrote JS recursive functions:
JOToTreeNode: function(RootEl,JO) {
var ti = document.createElementNS(XUL_NS,'treeitem');
ti.setAttribute("id",JO.id);
var tr = document.createElementNS(XUL_NS,'treerow');
ti.appendChild(tr);
var tc1 = document.createElementNS(XUL_NS,'treecell');
var tc2 = document.createElementNS(XUL_NS,'treecell');
tc1.setAttribute("label",JO.Name);
tc2.setAttribute("label",JO.Description);
tr.appendChild(tc1);
tr.appendChild(tc2);
if (JO.Children.length > 0) {
var child = document.createElementNS(XUL_NS,"treechildren");
ti.appendChild(child);
for (var i = 0; i < JO.Children.length; i++) {
UtilCommon.JOToTreeNode(child,JO.Children[i]);
}
};
RootEl.appendChild(ti);
}
...
UpdateTree: function(el) {
var els = el.getElementsByTagName("treechildren");
//Drop the previous tree
if(els.length > 0) {el.removeChild(els[0])};
//Get JSON tree of groups
var http = new XMLHttpRequest();
http.open("GET","http://"+this.host+":"+this.port+"/jsfolderstree",false);
http.send(null);
if (http.status == 200) {
var jtree = JSON.parse(http.responseText);
var child = document.createElementNS(XUL_NS,"treechildren");
el.appendChild(child);
for (var i = 0; i < jtree.Children.length; i++) {
UtilCommon.JOToTreeNode(child,jtree.Children[i]);
};
};
}
It works, but the tree contains only first level of nodes, e.g.:
- Bookmarks menu
- Bookmarks panel
- Tags
- Unassigned bookmarks
If I place code:
alert(JO.Name);
in UtilCommon.JOToTreeNode, I will see, that the sub-items like "123" and "Mozilla firefox" are exists, but doesn't add to tree as sub-items.
Where my mistake, how I can fix bug when sub-items doesn't attaches to the tree?
Thanks.
As per tree-XUL documentation, you should set the container=true for nested tree-items
...
if (JO.Children.length > 0) {
ti.setAttribute("container", true);
var child = document.createElementNS(XUL_NS,"treechildren");
ti.appendChild(child);
for (var i = 0; i < JO.Children.length; i++) {
UtilCommon.JOToTreeNode(child,JO.Children[i]);
}
};
...

Categories

Resources