Display JavaScript Object in HTML - javascript

I have a object that looks like this:
var grocery_list = {
"Banana": { category: "produce", price: 5.99 },
"Chocolate": { category: "candy", price: 2.75 },
"Wheat Bread": { category: "grains and breads", price: 2.99 }
}
And I want to be able to display each item in the object in HTML like this:
<div id="grocery_item" class="container">
<div class="item">Item Here</div>
<div class="category">Category Here</div>
<div class="price">Price Here</div>
</div>
I know how to loop through an Object in JS, but I'm not sure how to display those items in the DOM. I believe I could use the jQuery append function but I'm not sure how.
Any help would be appreciated. thanks!

This is how you can do it using jQuery (as you mention you'd like to use jQuery first). But it's not the best way how to it. If you're open to learn better methods then check some of the MV* frameworks (AngularJS, Ember etc.). Anyway, here is just an example:
var grocery_list = {
"Banana": { category: "produce", price: 5.99 },
"Chocolate": { category: "candy", price: 2.75 },
"Wheat Bread": { category: "grains and breads", price: 2.99 }
}
var wrapper = $('#wrapper'), container;
for (var key in grocery_list){
container = $('<div id="grocery_item" class="container"></div>');
wrapper.append(container);
container.append('<div class="item">' + key +'</div>');
container.append('<div class="category">' + grocery_list[key].category +'</div>');
container.append('<div class="price">' + grocery_list[key].price +'</div>');
}
jsfiddle here: http://jsfiddle.net/5jhgbg9w/
EDIT: Please, take this really as an example (which is OK since you're learning). As others pointed out - it's not the best method. Try to combine other examples, particularly the ones which do not compose HTML as a string. For easy tasks like this it's straightforward but the more code you would add, the messier the code becomes. I believe your "learning evolution" would get you there anyway :-) Cheers everyone
EDIT (2021): A lot of years have gone by since I answered this question. What about some more modern examples, just for fun? Without jQuery, just ES6:
const grocery_list = {
"Banana": { category: "produce", price: 5.99 },
"Chocolate": { category: "candy", price: 2.75 },
"Wheat Bread": { category: "grains and breads", price: 2.99 }
};
// since "grocery_list" is an object (not an array) we have do Object.keys()
const generatedHtml = Object.keys(grocery_list).reduce((accum, currKey) => accum +
`<div class="grocery_item">
<div class="item">${currKey}</div>
<div class="category">${grocery_list[currKey].category}</div>
<div class="price">${grocery_list[currKey].price}</div>
</div>`, '');
document.getElementById('container').innerHTML = generatedHtml;
.grocery_item{
padding: 5px;
}
.grocery_item:not(:last-child){
border-bottom: 1px solid #ccc;
}
<div id="container"></div>

You can create HTML elements with jQuery: $('<div>', {attr1: value, attr2: value}); This returns a new jQuery object so you can use it like jQuery element.
The jQuery.text() method: $('div').text('some text') This method is recommended if you putting just text inside the element. It will escape all special characters like '<'. Instead it puts &lt. This avoiding XSS attacks unlike jQuery.html() method.
You can look Security Considerations at jQuery docs about .html method.
// Create a div element with jQuery which will hold all items.
var $tree = $('<div>', {id: 'items-tree'});
//Loop all items and create elements for each
for (var key in grocery_list) {
var $gItem = $('<div>', {
id: 'grocery_item',
class: 'container'
});
var $item = $('<div>', {
class: 'item'
}).text(key);
$gItem.append($item);
var $category = $('<div>', {
class: 'category'
}).text(grocery_list[key].category);
$gItem.append($category);
var $price = $('<div>', {
class: 'price'
}).text(grocery_list[key].price);
$gItem.append($price);
$tree.append($gItem);
}
JSFiddle

It's old but you can try package html-stringify. As its introduction: "Converts Javascript Objects or Arrays to pretty HTML string for rendering in a browser."

The parent div <div id="grocery_item" class="container"> will be repeated for the no. of items in the grocery list.
The "id" of this parent div will be generated randomly for example item #index 0 will be "grocery_item0"
For each loop item create the parent div's first, then start appending the details to the parent div's using (another loop).
Below will be sample jquery,
$( ".grocery_item0" ).append( "" );

I will pass by the fact that your list definition is not exactly the best and I say this:
Using jQuery you could do that:
<script>
var _parent = $(".container").parent();
_parent.empty();
var _html;
$.each(grocery_list,function(prop, val){
_html = "<div id=\"grocery_item\" class=\"container\">";
_html += "<div class=\"item\">"+prop+"</div>";
_html += "<div class=\"category\">"+val.category+"</div>";
_html += "<div class=\"price\">"+val.price+"</div>";
_html += "</div>";
_parent.append(_html);
});
</script>
Note*: It's not recomanded to maanipulate the DOM by creating HTML strings. This is just an fast sample for your school assignment.

Related

How to apply json content for html attribute

I am trying to add json object for html arrtibute content but not working.I have tried many ways but I do not know how to set that.if any one know about that please help to resolve this issue.
javascript:
var validatorValue='{
"picker":{
"allow":
{
"message": "Content loram ipsom"
},
"past":
{
"message": "lorem issom"
}
}
}' ;
var daterestrictValue="{'range': {'start': '2019-10-30','end': '2019-12-30'}}";
var myinputValue="{'date':'tomorrow'}";
$("#mydiv").html("<div input="true" validator='+validatorValue+' date-restrict='+daterestrictValue+' my-input='+myinputValue+'></div>");
The main issue with your code (aside from line-breaks in string literals) it the mis-matched quotes in the HTML string you build. However, even after correcting those you will have issues placing serialised JSON within attributes as it too contains double quotes which will break the HTML syntax.
Also note that you're creating non-standard attributes in the HTML you create which may cause unexpected issues in your UI and JS.
An alternative way to approach this is to work with the values as objects (instead of strings). You can use jQuery to set the data of the element using those objects, like this:
var validatorValue = { "picker": { "allow": { "message": "Content loram ipsom" }, "past": { "message": "lorem issom" } } }
var daterestrictValue = { 'range': { 'start': '2019-10-30', 'end': '2019-12-30' } }
var myinputValue = { 'date': 'tomorrow' };
var $newDiv = $('<div data-input="true">Click me</div>').appendTo('#mydiv');
$newDiv.data({
"validator": validatorValue,
"date-restrict": daterestrictValue,
"my-input": myinputValue
});
// for testing
$('#mydiv div').on('click', function() {
console.log($(this).data('validator'));
console.log($(this).data('date-restrict'));
console.log($(this).data('my-input'));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="mydiv"></div>
this code save object in html element.
good luck
var validatorValue="{ 'picker':{'allow':{'message': 'Content loram ipsom'},'past':{'message': 'lorem issom'}}}";
var daterestrictValue="{'range': {'start': '2019-10-30','end': '2019-12-30'}}";
var myinputValue="{'date':'tomorrow'}";
$("#mydiv").html(`
<div input='true' validator="${validatorValue}" date-restrict="${daterestrictValue}" my-input="${myinputValue}">ggg</div>`);

Generate an HTML tree from JSON data

I have a one-file website... We all know bandwidth and internet are... yeah... That's why I only render parts of user interface when needded. Now I wanna take a step further and use JSON to store small parts of my website (trees of html elements) and generete the actual HTML on demand.
But I'm struggling to figure out how to "convert" the JSON object into plain old HTML. I found many topics and answers on how to achieve this, but none of those solved problems. I need a solution that could generate trees with ANY number of chid elements, inside of child elements and so on... All these solutions used .innerHTML which could literally void all my event handlers. I found nothing I wouldn't know already...
The JSON notation would look like this:
var htmlTree = {
'type': 'section',
'attr': {
'id': 'someID',
'class': 'someClass'
},
'content': 'section name',
'children': [
{
'type': 'h1',
'attr': {
'class': 'heading'
},
'content': 'Heading',
'children': [
{
'type': 'span',
'content': 'text'
},
{
'type': 'span',
'content': 'more text'
}
]
}
]
}
And the result would look like this:
<section id="someID" class="someClass">
section name
<h1 class="heading">
Heading
<span>text</span>
<span>more text</span>
</h1>
</section>
Does anybody know a solution to this problem? I really don't want to use any frameworks or libraries. I know it's a little hard to do something like this, that's why I'm asking here...
Bandwidth is cheap nowadays as the server supports gzip it takes even less. Why combine with more engaging Json and libraries to create HTML?
Instead of processing JSON, inject ready (parts) html - loaded via Ajax.
Try
http://www.json2html.com
You can try something like this but this make sense only if you have many same rows (and your data is really simple).
<html>
<body>
<div id="ct"></div>
<script>
var data = [{
"id" : 1,
"f" : "Arya",
"l" : "Stark"
},
{
"id" : 1,
"f" : "Jon",
"l" : "Snowk"
}];
var parent = document.getElementById("ct");
data.forEach( function (row) {
newDiv = document.createElement("div");
newDiv.innerHTML = "<h1>" + row.f + " " + row.l + "</h1>";
parent.append(newDiv);
})
</script>
</body>
</html>
The JSON.parse reviver can be used to transform key value pairs in JSON string :
var json = '{"type":"section","attr":{"id":"someID","class":"someClass"},"content":"section name","children":[{"type":"h1","attr":{"class":"heading"},"content":"Heading","children":[{"type":"span","content":"text"},{"type":"span","content":"more text"}]}]}'
var el = JSON.parse(json, function(k, v) {
if (!v.type) return v
var el = document.createElement(v.type)
el.textContent = v.content
for (k in v.attr || {})
el.setAttribute(k, v.attr[k])
for (var c of v.children || [])
el.append('\n', c)
return el
})
document.body.innerHTML = el.outerHTML
console.log( el.outerHTML )

How do I bind a javascript array to HTML while allowing adding and deleting from the array?

So the question is how can I keep the HTML elements in sync while I add and delete from an existing array.
If I have an array of javascript objects say element 1 is:
{
"firstName": "John",
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
....
]
.... ETC ETC COMPLICATED ....
}
Then my initial html might be generated by using the array index for each object of initial size 3 elements [ {}, {}, {} ]:
<div id="arrayPos-0">
<div>John</div>
<input>PROCESS<input>
<input>DELETE<input>
</div>
<div id="arrayPos-1">
<div>Sam</div>
<input>PROCESS<input>
<input>DELETE<input>
</div>
<div id="arrayPos-2">
<div>Timmy</div>
<input>PROCESS<input>
<input>DELETE<input>
</div>
If I add to the Javascript Array, and I expect to increment it and become [ {}, {}, {}, {} ]:
<div id="arrayPos-0">
...
</div>
<div id="arrayPos-1">
...
</div>
<div id="arrayPos-2">
...
</div>
<div id="arrayPos-3">
<div>Simone</div>
<input>PROCESS<input>
<input>DELETE<input>
</div>
However as soon as I delete from the javascript array say index 2 (arrayPos-2) I get the following HTML:
<div id="arrayPos-0">
...
</div>
<div id="arrayPos-1">
...
</div>
<div id="arrayPos-3">
...
</div>
This is all messed up and I'm unable to match "arrayPos-3" to now index 2. In addition when I add a new javascript object which is index 3:
<div id="arrayPos-0">
...
</div>
<div id="arrayPos-1">
...
</div>
<div id="arrayPos-3">
...
</div>
<div id="arrayPos-3">
...
</div>
I am not able to use AngularJS and hence ng-repeat can't be used due to support needed on older browsers. It would be pretty simple to use an observer to bind the javascript objects directly to the html markup.
I can only use jQuery and regular javascript.
But surely this can be solved in a simpler manner? Do I even need to bind by using IDs? Do I need to autogenerate GUIDs for IDs and use a dictionary to match ID with Javascript object index (I hope not)?
The simplest way is to have a generator function which will regenerate the HTML after any changes have been made (adding/deleting/editing).
That way you won't have any confusions with IDs and will always have your current JS object represented in the DOM. That's quite the "Angularish" way to do it - building the DOM from the JS data without really caring what's in the DOM.
Here's a super-simple example to see what I meant:
var data = [
{name: 'John'},
{name: 'Shomz'},
{name: 'Jimmy'}
]
var c = document.getElementById('c');
function build() {
var output = "";
for(var i = 0; i < data.length; i++) {
output += '<div id="arrayPos-' + i + '"><button onclick="del(' + i + ')">Del</button><button onclick="edit(' + i + ')">Edit</button>' + data[i].name + '</div>';
}
c.innerHTML = output;
}
function del(id) {
data.splice(id ,1);
document.getElementById('arrayPos-' + id).className = 'del';
setTimeout(build, 200);
}
function add() {
data.push({name: prompt('Enter name')});
build();
}
function edit(id) {
data[id].name = prompt('Enter name', data[id].name);
build();
}
build();
#arrayPos-0 {color: green}
button {margin: 4px}
#c div {opacity: 1; transition: all 0.2s linear}
#c div:hover {background: #eee}
#c div.del {opacity: 0}
<div id="c"></div>
<br>
<button onclick="add()">Add</button>
You could use JQuery's .attr() method to dynamically set the id property when looping through the objects in the array - if that's the approach you want to take. You could also look at dynamically setting the inner html using JQuery's .html() to set the contents of the divs. If you review traversing the DOM using JQuery it will help with the latter approach. Hope that helps -
If you want to keep it this way and keep them in order then you caan create a function that:
1.deletes the current divs
2. Re generates the divs in the new order with the corresponding new id's
And just have this function fire every time you add or delete something from the array. It's relatively simple and wont take all that long for javascript to do.
Or:
Create a for loop that loops through the array and identifies which position(number of loops) the object with "x" name is in the array and assigns it to the div.
You can use the jQuery .index() method to get the index of the element relative to its siblings. With that, you can match it to the index in the array. No need for adding id's to the elements.
Let's say you already have an index and you want to access the dom element. You can do this:
$('.class-name').get(index).remove();
Or if you're responding to some event and you're not sure which element in the array it corresponds to, you can do this:
$('.class-name').click(function(e){
var index = $('.class-name').index(e.target);
});
In my example I'm using a click event, but it can be any other way.
In-case, if you can modify your existing js object, I suggest to use id for both html element and the js object.
Probably you could go for something:
var id = Math.random().toString(16).slice(-6); // for random id, aplha-numeric
Your html:
<div id="23xc45">
...
</div>
<div id="cd567u">
...
</div>
Your js object:
[{
"id" : "23xc45",
"firstName": "John",
...
},{
"id" : "cd567u",
"firstName": "Sam",
...
}]

angularjs data binding with dynamically created elements

I have this code in my application:
$scope.appendBets = function()
{
$.each($scope.phaseBets, function(i, bet)
{
var betElement = angular.element('<div ng-model="phaseBets[i]">Bet id: {{phaseBets[i].id}}</div>');
angular.element(document.querySelector('#betsHolder')).append(betElement);
$compile(betElement)($scope);
});
}
the $scope.phaseBets is loaded from $http.get.
Now the problem is that the {{phaseBets[i].id}} content not seen on the html page, I am getting this Bet id:.
I have seen this OS but it's not working for me, maybe because of the array.
Is there anything wrong with my code?
Note
The thing is that by the I'd I will create an element (different for each id) so ng-repeat not helping that mutch.
Here's how I'd do it using ng-repeat and ng-include:
$scope.items = [
{id: 1, title: 'foo', data: {body: 'baz1'}},
{id: 2, title: 'bar', data: {body: 'baz2'}}
];
<div ng-repeat="item in items">
<h2>{{item.title}}</h2>
<div ng-include src="getTemplateById(item.id)"></div>
</div>
Where the templates are defined inline like this:
<script type="text/ng-template" id="template-1.html">
Content of template-1.html
<div>{{item.data.body}}</div>
</script>
<script type="text/ng-template" id="template-2.html">
<p>Content of template-2.html</p>
</script>
and getTemplateById is:
$scope.getTemplateById = function(id) {
return 'template-' + id + '.html';
};
You can see it in action here.
I think you got it from wrong side, in angularjs controllers/data drives the view, here you are creating elements (and even worse adding them to page) in loop (expensive DOM operations)
I'd replace your code with following
<div id="betsHolder">
<div ng-repeat="bet in phaseBets track by bet.id">Bet id: {{bet.id}}</div>
</div>
as soon as you assign your array/object to $scope.phaseBets the DOM will be created
but using ng-repeat is better option,
angular.forEach($scope.phaseBets, function(bet, i)
{
var betElement = angular.element('<div ng-model="bet">Bet id: {{bet.id}}</div>');
angular.element(document.querySelector('#betsHolder')).append(betElement);
$compile(betElement)($scope);
});

Building html from an ajax call to jquery UIs sortable list

Im having a design problem in HTML/JavaScript.
I appended jquery UIs sortable to my web-application:
Heres a demo on sortable (cant show my application now):
http://jqueryui.com/demos/sortable/default.html
Now im populating that drag and drop list in JavaScript with data from an ajax call. The list is changed by users all the time.
I try do something like this:
Var htmlData = '<div id=wrapper>'
+'<div>'
+data.title
+'</div>'
+'<div>'
+data.description
+'</div>';
${"#sortable-list"}.html(htmlData);
And so on. Some of the divs also have attributes set in variables like 'id="' + data.id + '"'
I then try to fit this string htmldata in the sortable-list. But it's getting messy pretty quick.
I tried to fit <tables> in it, and <p> with <span>s in. But it's still hard to get the design that I want.
Cant post images due to lack of reputation but here's the design i want (this is just one <li> in the <ul>):
http://img546.imageshack.us/img546/9179/48361880.gif http://img546.imageshack.us/img546/9179/48361880.gif
So how would you do this? I've been reading about templates like mustache but it don't seems to help me.
And the way I building the table with a string can't be the best way.
Any example or info on how to do this is much appreciated
There are many advantages of client side tempting but the main one is that you don't have to mess with stringing HTML together in JavaScript. Doing so is not only error prone but it also quickly becomes a maintenance nightmare.
For example here's how you could tackle your requirements with Underscore.js tempting.
As you can see the HTML is clearly laid out and will be easy to alter as your requirements change.
<script type="text/template" id="sortable-entry">
<% _.each(items, function(item) { %>
<div>Title: <%= item.title %></div>
<div>Description: <%= item.description %></div>
<hr />
<% }); %>
</script>
<ul id="sortable-list"></ul>​
<script>
var data = {
items: [
{ title: 'title1', description: 'description1' },
{ title: 'title2', description: 'description2' },
{ title: 'title3', description: 'description3' },
{ title: 'title4', description: 'description4' },
{ title: 'title5', description: 'description5' }
]
};
var event_html = _.template($('#sortable-entry').html());
$(event_html(data)).appendTo($('#sortable-list'));
</script>
Here's a live example of this - http://jsfiddle.net/tj_vantoll/kmXUr/.
You could do something like this.
var items[]
items.push($('<div />', { html: data.title }));
items.push($('<div />', { html: data.description}));
$("#sortable-list").html($('<div />', {
'id' : 'wrapper',
'class' : 'yourclass',
html: items.join('')
})
);
the items.push you can use in a loop to cycle all data and push items into the array. Later join the array items into the html

Categories

Resources