Adding JSON items to an HTML list using JQuery - javascript

I am adding items from a JSON file using JQuery to an HTML page dynamically.
HTML:
<div id='cssmenu'>
<ul id='options'>
<li class='active'><a href='#'><span>Home</span></a>
<ul id='home'></ul></li>
<li class='has-sub'><a href='#'><span>Products</span></a>
<ul id='product_list'></ul></li>
<li class='has-sub'><a href='#'><span>Company</span></a>
<ul id='company'></ul></li>
<li class='has-sub'><a href='#'><span>Contact</span></a>
<ul id='contact'></ul></li>
</ul>
</div>
JQuery:
$(document).ready(function () {
$.getJSON('../JSON/cwdata.json', function (cwData) {
// Add the product categories
$.each(cwData.product, function (i, product) {
var option_cate = ('<li class="item">' + product.category + '</li>');
$('#product_list').append(option_cate);
// Add the product names
$.each(product.items, function (i, item) {
var option_name = ('<ul class="details" style="display: none;"><li class="name">' + item.name + '</li></ul>');
$(".item").append(option_name);
}); //$.each(...)
}); //$.each(...)
}); //$.getJSON
}); //$document
JSON(cwdata.json file):
{
"product": [
{
"category": "Product 1",
"items": [
{
"name": "Item 1.1",
"name": "Item 1.2"
}
]
},
{
"category": "Product 2",
"items": [
{
"name": "Item 2"
}
]
},
{
"category": "Product 3",
"items": [
{
"name": "Item 3"
}
]
}
]
}
The problem is the data is being added the wrong way. The HTML looks like this after the page has been loaded:
.
Item 1, Item 2 and Item 3 are being added to Product 1, whereas I only want all the "items" under "Product 1" to be in the the Product 1 list.
Basically:
Product 1
- Item 1.1
- Item 1.2
But I am getting:
Product 1
- Item 1.1
- Item 2
- Item 3
Any tips would be appreciated.

Ok.. I found several bugs in your solution..
First this is a modified working version
Now please note that your iteration:
$.each(product.items, function (i, item) {
Does not iterate properly because you have only one object inside the array so instead each item should be an independent object {"name": "bla bla bla"}
Second you append the items to ALL .item and add a UL for every item and that's also buggy.. please review my code and let me know if it helps.

Your json is wrong.
For example:
Instead of
"items": [
{
"name": "Item 1.1",
"name": "Item 1.2"
}
]
It should be:
"items": [
{ "name": "Item 1.1" },
{ "name": "Item 1.2" }
]
Once that is corrected, you can change your code as -
$.each(cwData.product, function (i, product) {
var option_cate = ('<li class="item">' + product.category + '</li>');
$('#product_list').append(option_cate);
var html = '<ul class="details">';
$.each(product.items, function (i, item) {
html += ('<li class="name">' + item.name + '</li>');
});
html += '</ul>'
$('#product_list').append(html);
});

You are appending results to the class item which exists in three places. So it is appended to the three <li class="items">.
Try giving id to your <li> tags like <li id="product1">... instead <li class="item">

This:
$(".item").append(option_name);
selects all html tags with class item. So you are appending the details to all existing <li class="item">.
Use a more especific selector to add the new content to your list element.

As per my view you have to correct your JSON like:
{
"product": [
{
"category": "Product 1",
"items": ["Item 1-1","Item 1-2","Item 1-3"]
},
{
"category": "Product 2",
"items": ["Item 2-1","Item 2-2","Item 2-3"]
},
{
"category": "Product 3",
"items": ["Item 3-1", "Item 3-2","Item 3-3"]
}
]
}
Then use below code I hope it will work for you:
<script>
$(document).ready(function () {
$.getJSON('cwdata.json', function (cwData) {
// Add the product categories
$.each(cwData.product, function (i, product) {
var option_cate = ('<li class="item'+i+'">' + product.category + '</li>');
//alert(dump(product.items));
//alert(product.items.length);
$('#product_list').append(option_cate);
// Add the product names
for(var k=0;k<(product.items.length);k++){
var option_name = ('<ul class="details"><li class="name">' + product.items[k] + '</li></ul>');
//console.log(option_name);
$(".item"+i).append(option_name);
}
}); //$.each(...)
}); //$.getJSON
}); //$document
</script>
Enjoy..... :)

It will be work
Use json formate like this
{
"product": [
{
"category": "Product 1",
"items": [
{ "name": "Item 1.1" },
{ "name": "Item 1.2" }
]
},
{
"category": "Product 2",
"items": [
{
"name": "Item 2"
}
]
},
{
"category": "Product 3",
"items": [
{
"name": "Item 3"
}
]
}
]
}
And correct your script like
$(document).ready(function () {
$.getJSON('test.json', function (cwData) {
// Add the product categories
$.each(cwData.product, function (i, product) {
var option_cate = ('<li class="item">' + product.category + '</li>');
$('#product_list').append(option_cate);
// Add the product names
$.each(product.items, function (i, item) {
var option_name = ('<ul class="details" style=""><li class="name">' + item.name + '</li></ul>');
$(".item:last").append(option_name);
}); //$.each(...)
}); //$.each(...)
}); //$.getJSON
}); //$document
I hope it will work.

If you are getting json data as a string from c#, then you need to parse to json in javascript.
function success(response) {
$('.listboxclass').empty();
$('.listboxclass').append('<option value="0">Select</option>');
$.each(JSON.parse(response.d), function(i, obj) {
$('.listboxclass').append('<option value="'+obj.id+'">'+obj.name+'</option>');
});
}
Here listboxclass is the classname of the listbox.
Here is the c# web method code which returns to ajax call.
[WebMethod]
public static string GetScreenList(string tId)
{
return "[{\"id\":\"1\",\"name\":\"aaa\"},{\"id\":\"2\",\"name\":\"bbb\"}]";
}

Related

get previous json item in Json

I have a JSON file titled stuff.json. I am trying to get the previous json item given a certain item. For example, if I am given the key ["also-random-here"], how do I get the previous JSON item "sample-name"?
My JSON data looks as follows:
{
"random-name-here": {
"name": "name is item1"
},
"sample-name": {
"name": "name is item2"
},
"also-random-here": {
"name": "name is item3"
}
}
try this
var names={
"random-name-here": {
"name": "name is item1"
},
"sample-name": {
"name": "name is item2"
},
"also-random-here": {
"name": "name is item3"
}
};
var prevName= findPrevName(names, "also-random-here") ;
function findPrevName(item, key) {
var prevName;
for (const property in item)
{
if(property==key) break;
prevName=property;
};
return { [prevName]: item[prevName]};
};

How to get html nested structure with ul, li for a tree data array

Hi i want to get nested tree structure based on nesting
Something like this
<ul>
<li>Root
<ul>
<li>First level item 1</li>
<li>
First level item 2
<ul>
<li>second level item1</li>
</ul>
</li>
</ul>
</li>
Question: my function is not returning tree structure markup properly.
Note: i don't want to add 1 more loop
Here is what i have tried:
var getTreeStrucureTemplate = dataset => {
var hashTable = Object.create(null), ul = '',li = '';
dataset.forEach(function(aData){
hashTable[aData.id] = {...aData, childNodes: []};
ul = '<ul>';
});
var dataTree = [];
dataset.forEach(aData => {
if(aData.parentId) { hashTable[aData.parentId].childNodes.push(hashTable[aData.id]); ul += '<li>'+aData.name+'</li>';}
else { dataTree.push(hashTable[aData.id]); ul += '</ul><ul>' }
// console.log(ul);
});
//console.log(dataTree);
var treeStructure = ul;
return treeStructure;
};
var list = [
{
"parentId": 0,
"id": 1,
"name": "Root"
},
{
"parentId": 1,
"id": 2,
"name": "First Level item 1"
},
{
"parentId": 1,
"id": 3,
"name": "First Level item 2"
},
{
"parentId": 3,
"id": 4,
"name": "second Level item 1"
}
];
console.log(getTreeStrucureTemplate(list))
This is how I would go about this:
Use a nested data structure with each object containing it's children
Use a set of recursive functions that call each other to automatically deal with any number of layers
(It only runs as many times as needed, but whether your consider recursive functions as loops is up to you)
var getListItems = dataset => {
// Create a string containing the items for this list
return dataset.map(item => {
// Build a nested UL string by calling getTreeStrucureTemplate on this objects children
var nested = getTreeStrucureTemplate(item.children || [])
// Build the current item and add any nested lists
return `<li>${ item.name }</li>${ nested }`
}).join('') // Join the items into a single string
}
var getTreeStrucureTemplate = dataset => {
// Only wrap the list in UL if it has contents
if (dataset.length) {
return `<ul>${ getListItems(dataset) }</ul>`
} else {
return ''
}
};
var list = [{
"name": "A",
"children": [{
"name": "B",
"children": [{
"name": "C"
},
{
"name": "D"
}]
}]
},
{
"name": "E",
"children": [{
"name": "F"
}]
}
]
var test = getTreeStrucureTemplate(list)
document.getElementById('test').innerHTML = test
console.log(test)
<div id="test"></div>
I tried to work with the structure that you have given here in your question. I don't really understand where you don't want to use another loop, but here is my suggestion to resolve your problem.
var getTreeStrucureTemplate = dataset => {
var hashTable = {}, ul = '',li = '';
var dataTree = [];
dataset.forEach(item => {
if (item.parentId) {
if (hashTable[item.parentId]) {
hashTable[item.parentId].childNodes.push(item);
} else {
hashTable[item.parentId] = {id: item.patentId, childNodes: [item]};
}
} else {
hashTable[item.id] = {...item, childNodes: []};
}
});
console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-');
console.log(hashTable)
console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-');
Object.values(hashTable).forEach(node => {
ul += '<ul>' + node.name;
node.childNodes.forEach(subNode => {
ul += '<li>' + subNode.name + '</li>';
});
ul += '</ul>';
})
return ul;
};
var list = [
{
"parentId": 0,
"id": 1,
"name": "First Level"
},
{
"parentId": 1,
"id": 2,
"name": "First Level item 1"
},
{
"parentId": 0,
"id": 3,
"name": "First Level 2"
},
{
"parentId": 3,
"id": 4,
"name": "First Level 2 item 1"
}
];
console.log(getTreeStrucureTemplate(list))
I am printing the array after it is reformatted to the desired way.
I think you can improve this code in terms of performance if you see fit, but the way it is written here should be pretty clear about what we are trying to accomplish.
I hope it would help.
updated version to support as many nested levels as you would like:
var getTreeStrucureTemplate = dataset => {
var hashTable = {}, ul = '',li = '';
var dataTree = [];
dataset.forEach(item => {
if (item.parentId) {
if (hashTable[item.parentId]) {
hashTable[item.parentId].childNodes.push(item);
} else {
hashTable[item.parentId] = {id: item.patentId, childNodes: [item]};
}
} else {
hashTable[item.id] = {...item, childNodes: []};
}
});
console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-');
console.log(hashTable)
console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-');
Object.values(hashTable).forEach(node => {
ul += createSubTree(node);
})
return ul;
};
var createSubTree = tree => {
var str = '';
str += '<ul>' + tree.name;
tree.childNodes.forEach(subNode => {
str += '<li>' + subNode.name + '</li>';
if (subNode.childNodes && subNode.childNodes.length) {
str += createSubTree(subNode.childNodes);
}
});
str += '</ul>';
return str;
}
var list = [
{
"parentId": 0,
"id": 1,
"name": "First Level"
},
{
"parentId": 1,
"id": 2,
"name": "First Level item 1"
},
{
"parentId": 0,
"id": 3,
"name": "First Level 2"
},
{
"parentId": 3,
"id": 4,
"name": "First Level 2 item 1"
}
];
console.log(getTreeStrucureTemplate(list))
is that what you are looking for?

AngularJS use one object as a filter for another

I'm trying to filter my ng-repeat through a set of checkboxes which come from a different object. Object 1 holds my categories and object 2 holds all my articles.
The categores object will turn into checkboxes. These checkboxes should act as filter for the articles. An article can have mutliple categories.
$scope.categories:
[
{
"id": "1",
"title": "Blog"
},
{
"id": "2",
"title": "News"
}
]
$scope.articles:
[
{
"id": "1",
"title": "Whats going on",
"categories":{
"results" : [1,2,3]
}
},
{
"id": "2",
"title": "Trump!",
"categories":{
"results" : [3]
}
}
]
Checkboxes:
<div class="filter-pills" ng-repeat="cat in categories">
<input type="checkbox" ng-model="filter[cat.Id]" ng-checked="cat.checked"/>{{cat.Title}}
</div>
ng-repeat:
<div class="col-lg-3 col-md-4" ng-repeat="item in articlesFinal"></div>
I have tried different solutions like ng-change when i update my filter array and compare it to the object used in ng-repeat.
I can't seem to figure this one out. Any suggestions?
Try this
<div class="filter-pills" ng-repeat="cat in categories">
<input type="checkbox" ng-model="cat.checked"/>{{cat.title}}
</div>
<div class="col-lg-3 col-md-4" ng-repeat="item in articles | filter: catFilter">{{item.title}}</div>
and in controller
$scope.catFilter = function (article) {
var checkedCats = vm.categories.filter(function (cat) {
return cat.checked;
});
// no filter, show all
if(checkedCats.length == 0) return true;
for(var i = 0; i < checkedCats.length; i++){
var id = checkedCats[i].id;
if(article.categories.results.indexOf(id) >= 0){
return true;
}
}
// no match, then false
return false
};
Also notice that category id should be integer, not string
$scope.categories = [
{
"id": 1, // integer
"title": "Blog"
},
{
"id": 2,
"title": "News"
}
];
$scope.articles = [
{
"id": "1",
"title": "Whats going on",
"categories":{
"results" : [1,2,3] // integer
}
},
{
"id": "2",
"title": "Trump!",
"categories":{
"results" : [3]
}
}
];

Loading data from JSON file into Tree with checkboxes

I am trying to create a expanding tree for my web application but I am not able to bring data from a JSON file to dynamically fill the tree. I found this code from another post on SOF.
Here is my JSON file called tree_data.json :
{
"Data": {
"id": "0",
"title": "root-not displayed",
"children": {
"id": "1",
"title": "Option 1",
"children": {
"id": "11",
"title": "Option 11",
"children": {
"id": "111",
"title": "Option 111",
"id": "112",
"title": "Option 112"
}
}
}
}
}
Here is javascript code imbedded within HTML:
$.getJSON("tree_data.json", function(treedata) ){
//$.each(treedata.data, function(i, field){
$(function () {
addItem($('#root'), treedata); //first call to add item which passes the main parent/root.
$(':checkbox').change(function () {
$(this).closest('li').children('ul').slideToggle();
});
$('label').click(function(){
$(this).closest('li').find(':checkbox').trigger('click');
});
});//}
function addItem(parentUL, branch) {
for (var key in branch.children) { //for each key in child in data
var item = branch.children[key]; //assign each child in variable item
$item = $('<li>', { //jquery object
id: "item" + item.id
});
$item.append($('<input>', { //add check boxes
type: "checkbox",
id: "item" + item.id,
name: "item" + item.id
}));
$item.append($('<label>', { //add labels to HTML. For every id, display its title.
for: "item" + item.id,
text: item.title
}));
parentUL.append($item);
if (item.children) {
var $ul = $('<ul>', {
style: 'display: none'
}).appendTo($item);
$item.append();
addItem($ul, item); //recursive call to add another item if there are more children.
}
}
}}
I need a lot of help changing this code in order grab the JSON data and creating the tree. Any help would be very appreciated. Thank you.
First of all, you have to encapsulate every children object in a json array, so you can have single or multiple object in each children (like 111 and 112). So change the json to be like that:
{
"Data": {
"id": "0",
"title": "root-not displayed",
"children": [{
"id": "1",
"title": "Option 1",
"children": [{
"id": "11",
"title": "Option 11",
"children": [{
"id": "111",
"title": "Option 111"
},
{
"id": "112",
"title": "Option 112"
}]
}]
}]
}
}
Now, there is a working code base (with working example):
$(function () {
var treedata = JSON.parse('{"Data": {"id": "0","title": "root-not displayed","children": [{ "id":"1","title":"Option 1","children": [{"id": "11","title": "Option 11","children": [{"id": "111","title": "Option 111"},{"id": "112","title": "Option 112"}]}]}]}}'); //JUST FOR MOCKUP THE JSON CALL
addItem($('#root'), treedata.Data); //first call to add item which passes the main parent/root.
$(':checkbox').change(function () {
$(this).closest('li').children('ul').slideToggle();
});
$('label').click(function(){
$(this).closest('li').find(':checkbox').trigger('click');
});
});//}
function addItem(parentUL, branch) {
$.each(branch.children, function(i){
var item = branch.children[i]; //assign each child in variable item
$item = $('<li>', { //jquery object
id: "item" + item.id
});
$item.append($('<input>', { //add check boxes
type: "checkbox",
id: "item" + item.id,
name: "item" + item.id
}));
$item.append($('<label>', { //add labels to HTML. For every id, display its title.
for: "item" + item.id,
text: item.title
}));
parentUL.append($item);
if (item.children) {
var $ul = $('<ul>', {
}).appendTo($item);
addItem($ul, item); //recursive call to add another item if there are more children.
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="root">
</div>
Now just use your getJSON instead of my mockup data and you will be fine i hope :)

How to get JSON sub array data from array with equal option and value with Mustache.js?

I am trying to work with Mustache.js that is really helping.
I am stuck on getting array with specific option and value.
My JSON is looking like that:
{
"departments": [
{
"department": [
{
"id": 114,
"deptName": "Department 1",
"category": [
{
"id": 127,
"catName": "Category Name",
"subCategory": []
},
{
"id": 115,
"catName": "Category Name",
"subCategory": []
}
]
}
]
},
{
"department": [
{
"id": 123,
"deptName": "Department 2",
"category": [
{
"id": 126,
"catName": "Category Name",
"subCategory": []
},
{
"id": 124,
"catName": "Category Name",
"subCategory": []
}
]
}
]
}
]
}
To get main department names it is easy as:
JS:
$.ajax({
url: 'link_to_json',
dataType: 'json',
success: function(data) {
var template = $('#pageHomeTpl').html();
var html = Mustache.to_html(template, data);
$('#category-list').html(html);
}
});
HTML:
<ul id="category-list">
<script id="pageHomeTpl" type="text/template">
{{#departments}}
{{#department}}
<li>{{deptName}}</li>
{{/department}}
{{/departments}}
</script>
</ul>
But now I need to somehow get categories ("category:") from department with specific ID, for example "id": 114.
Any help, please.
You can try in these lines, with jQuery map() and grep()
console.log(JSON.stringify(data));
var filtereddata = {"departments" : []};
var filtereddept= {};
filtereddept.department= $.map(data.departments, function(alldept,indx){
return $.grep(alldept.department, function(deptobj,indx){
return deptobj.id==114;
});
});
filtereddata.departments[0]=filtereddept;
console.log(JSON.stringify(filtereddata));
The template to iterate the category of departments:
<script id="pageHomeTpl" type="text/template">
{{#departments}}
{{#department}}
<li>{{deptName}}</li>
{{#category}}
<ul>
<li>{{catName}}</li>
</ul>
{{/category}}
{{/department}}
{{/departments}}
</script>
I don't test it but it seems to be work...
...
success: function(data) {
var template = $('#pageHomeTpl').html();
var item = data.departments
for(key in item){
if(key == 'id' && item[key] == 114 ){
var html = Mustache.to_html(template, item);
}
}
$('#category-list').html(html);
}
...
with FOR .. IN statement you can cycle in your object or array take look at this link
js_loop_for_in

Categories

Resources