How to inject data from JSON to HTML - javascript

I am working on a small project to read JSON file and insert each object into a DIV in already existed HTML. So if you check the below, I need id and class from JSON file to show up under this order:
"id": external-events-list "class": fc-event fc-h-event.fc-daygrid-event.fc-daygrid-block-event.fc-event-main
The issue is, I can't get it to work to go where I want it. Please check this JS Code:
<script>
$(document).ready(function () {
$.getJSON("resources.json",
function (data) {
var employee = '';
$.each(data, function (key, value) {
//CONSTRUCTION OF ROWS HAVING
// DATA FROM JSON OBJECT
employee += '<tr>';
employee += '<td>' +
value.id + '</td>'; // THe ID is showing up - So like this it works!
employee += '<div class="fc-event-main">' + '<div class="fc-event.fc-h-event.fc-daygrid-event.fc-daygrid-block-event">' +
value.title + '</div>' + '</div>'; //But this Doesn't WORK!
});
//INSERTING ROWS INTO TABLE
$('.fc-event-main').append(employee);
});
});
</script>
And here is the HTML Code:
<body>
<div id='wrap'>
<div id='external-events'>
<div id='external-events-list'>
<div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
<div class='fc-event-main'>Employee 1</div>
</div>
<div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
<div class='fc-event-main'>Employee 2</div>
</div>
</div>
</body>
</html>
and the JSON code that I'm reading is like:
[
{
"id": "1",
"title": "John",
},
{
"id": "2",
"title": "Tom",
}
]

Its hard to tell what exactly you want this script to do because you're mixing table cells with div tags and a list that appends every div with a class tag. There are many little mistakes. Here's my interpretation. Take a look. Notice I've used backticks and template literals to display the data. This makes the code cleaner and easier to read.
$(document).ready(function() {
// $.getJSON("resources.json",
// function(data) {
let data = [{
"id": "1",
"title": "John",
},
{
"id": "2",
"title": "Tom",
}
]
let employee = '';
$.each(data, function(key, value) {
employee += `<div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
<div class='fc-event-main'>Employee ${key+1}</div>
<table><tr><td>${value.id}</td>
<td><div class="fc-event-main">
<div class="fc-event.fc-h-event.fc-daygrid-event.fc-daygrid-block-event">${value.title}</div>
</div></td></tr></table>
</div>`;
});
//INSERTING ROWS INTO TABLE
$('#external-events-list').append(employee);
// });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='wrap'>
<div id='external-events'>
<div id='external-events-list'>
</div>
</div>
</div>

If you want something a little more robust and abstracted, you might find this interesting, apply to styling/classes as needed.
If working with items you might want to be adding and removing, you should work on the object then run a render function to render things, this is especially important if you're adding click events to things.
let employee = (function() {
let root, form, data = []
function init(elm, items) {
root = elm
data = items
render()
}
function cancel() {
form.find('[name="title"], [name="id"]').val('')
form.find('.add').show()
form.find('.update, .cancel').hide()
}
function add(id, title) {
data.push({
id: data.length ? parseInt(data[data.length - 1].id, 10) + 1 : 1,
title: form.find('[name="title"]').val()
})
cancel()
render()
}
function edit(item) {
form.find('[name="id"]').val(item.id)
form.find('[name="title"]').val(item.title)
form.find('.add').hide()
form.find('.update, .cancel').show()
}
function update() {
let id = parseInt(form.find('[name="id"]').val(), 10)
data.splice(data.findIndex(v => v.id === id), 1, {
id,
title: form.find('[name="title"]').val()
})
cancel()
render()
}
function remove(item) {
data.splice(data.indexOf(item), 1)
render()
}
function render() {
root.empty()
form = $(`
<form>
<input type="hidden" name="id" />
<input type="text" name="title" />
<button type="button" class="add">+</button>
<button type="button" class="update">✔️</button>
<button type="button" class="cancel">x</button>
</form>
`)
form.find('.add').click(add)
form.find('.update').hide().click(update)
form.find('.cancel').hide().click(cancel)
let list = $('<div id="events-list" />')
$.each(data, function(key, value) {
let item = $(`
<div>
<div>
Employee ${parseInt(value.id, 10)} - ${$('<span/>').text(value.title).text()}
<button class="delete">X</button> <button class="edit">Edit</button>
</div>
</div>
`)
item.find('.delete').click(() => remove(value))
item.find('.edit').click(() => edit(value))
list.append(item)
})
root.append(list)
root.append(form)
}
return {
init
}
})()
$(document).ready(function() {
// $.getJSON("resources.json", function(data) {
let data = [{
"id": "1",
"title": "John",
},
{
"id": "2",
"title": "Tom",
}
]
employee.init($('#events'), data || [])
//})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='events'></div>

Related

Jquery append method returning html tags instead of the proper formats

The feature is for a quiz and im retrieving the data for the quiz that is the questions and answers and appending it to my div having id test_box. The data has been successfully retrieved but instead of proper formatting the data, it is returning me in form of html tags.
Here is my code snippet:
const url = window.location.href
const testBox = document.getElementById('test_box')
$.ajax({
type: 'GET',
url: `${url}/data`,
success: function(response){
const data = response.data
data.forEach(element => {
for (const [question, answers] of Object.entries(element)){
testBox.append(`
<div class="question_box">
<div>
<b>${question}</b>
</div>
`);
answers.forEach(answer => {
testBox.append(`
<div>
<input type="radio" class="ans" id=${question}-${answer}" name="${question}"
value="${answer}">
<label for="${question}">${answer}</label>
</div>
`)
})
testBox.append(`</div>`);
}
});
},
error: function(error){
console.log(error)
}
});
output of response.data
Array(2)0: {1000-100 = ?: Array(4)}1: {1 + 1 = ?: Array(4)}length:
2__proto__:
Array(0)
You can first append your outer div i.e : question_box inside your dom and then to append option inside your question_box you can use $("#test_box .question_box:last") this will target last question_box added and will append options there .
Demo Code :
//just for demo..
var data = [{
"1000 - 100 = ?": ["a", "v", "c", "d"]
}, {
" 1 + 1 = ?": ["a", "v", "c", "d"]
}]
data.forEach(element => {
for (const [question, answers] of Object.entries(element)) {
//use it like this..
$("#test_box").append(`
<div class="question_box">
<div>
<b>${question}</b>
</div>
</div>`);
answers.forEach(answer => {
//now to append inside question_box use :last
$("#test_box .question_box:last").append(`
<div>
<input type="radio" class="ans" id=${question}-${answer}" name="${question}"
value="${answer}">
<label for="${question}">${answer}</label>
</div>
`)
})
}
});
.question_box {
border: 1px solid
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="test_box"></div>

Why does the checkbox keep being unchecked by this javascript?

I have an issue with the following js. It sounds very silly but the following js keeps unchecking the 2 first checkbox (in <div id="shortcut1"></div> and <div id="shortcut2"></div>).
I tested the script with different option, changing the params in cmdInfo. My conclusion is that no matter what the script will never check the 2 first checkbox at the end.
Do you have any idea regarding the issue. I spend hours on this but I can't figure out.
Thanks a lot for your help !
https://jsfiddle.net/bqaude3h/2/
const URL_PLACEHOLDER = 'your url'
let commands = [
{ name: "shortcut1", description: null, shortcut: "Alt+W" },
{ name: "shortcut2", description: null, shortcut: "Alt+Q" },
{ name: "shortcut3", description: null, shortcut: "Alt+S" }
]
let cmdInfo = {
"shortcut1": {
"storeSearchHistory": true,
"url": "https://test.com",
"history": ['test']
},
"shortcut2": {
"storeSearchHistory": false,
"url": ""
},
"shortcut3": {
"storeSearchHistory": true,
"url": ""
}
}
let html, div, existingHistory;
commands.forEach(cmd => {
html = `
<div id="${cmd.name}" class="sc-div">
<div class="flex-container">
<input type="text" class="shortcut" value="${cmd.shortcut}" />
<input type="url" class="url" placeholder="${URL_PLACEHOLDER}"
value="${cmdInfo[cmd.name].url}" />
</div>
<div class="history-div">
<button>View search history</button>
<input type="checkbox" class="store-search-history" />
<label><small>Save search history</small></label>
</div>
</div>
`
document.querySelector('#shortcuts').innerHTML += html;
try {
existingHistory = Boolean(cmdInfo[cmd.name].history.length)
} catch {
existingHistory = false;
}
div = document.getElementById(cmd.name);
div.querySelector('button').disabled = !existingHistory;
div.querySelector('.store-search-history').checked = cmdInfo[cmd.name].storeSearchHistory;
});
The issue is with this line:
document.querySelector('#shortcuts').innerHTML += html;
You can read about Why is “element.innerHTML+=” bad code?. Basically, the browser will re-parse the constructed DOM multiple times which might cause to break reference.
This is a working example:
let commands = [{
name: "shortcut1",
description: null,
shortcut: "Alt+W"
},
{
name: "shortcut2",
description: null,
shortcut: "Alt+Q"
},
{
name: "shortcut3",
description: null,
shortcut: "Alt+S"
}
]
let cmdInfo = {
"shortcut1": {
"storeSearchHistory": true,
"url": "https://some_url.com"
},
"shortcut2": {
"storeSearchHistory": false,
"url": ""
},
"shortcut3": {
"storeSearchHistory": true,
"url": ""
}
}
let html, div, existingHistory, URL_PLACEHOLDER;
commands.forEach(cmd => {
html = `
<div id="${cmd.name}" class="sc-div">
<div class="flex-container">
<input type="text" class="shortcut" value="${cmd.shortcut}" />
<input type="url" class="url" placeholder="${URL_PLACEHOLDER}"
value="${cmdInfo[cmd.name].url}" />
</div>
<div class="history-div">
<button>
<img src="icons/box-open-solid.svg"> View search history
</button>
<input type="checkbox" class="store-search-history" />
<label><small>Save search history</small></label>
</div>
</div>
`
//document.querySelector('#shortcuts').innerHTML += html;
document.querySelector('#shortcuts').insertAdjacentHTML('beforeend', html);
try {
existingHistory = Boolean(cmdInfo[cmd.name].history.length)
} catch (e) {
existingHistory = false;
}
div = document.getElementById(cmd.name);
div.querySelector('button').disabled = !existingHistory;
div.querySelector('.store-search-history').checked = cmdInfo[cmd.name].storeSearchHistory;
});
<div id='shortcuts'>
</div>
You may use the conditional rendering for the input tag.
let commands = [
{ name: "shortcut1", description: null, shortcut: "Alt+W" },
{ name: "shortcut2", description: null, shortcut: "Alt+Q" },
{ name: "shortcut3", description: null, shortcut: "Alt+S" }
]
let cmdInfo = {
"shortcut1": {
"storeSearchHistory": true,
"url": "https://some_url.com"
},
"shortcut2": {
"storeSearchHistory": false,
"url": ""
},
"shortcut3": {
"storeSearchHistory": true,
"url": ""
}
}
let html, div, existingHistory;
let URL_PLACEHOLDER="your placeholder"
commands.forEach(cmd => {
html = `
<div id="${cmd.name}" class="sc-div">
<div class="flex-container">
<input type="text" class="shortcut" value="${cmd.shortcut}" />
<input type="url" class="url" placeholder="${URL_PLACEHOLDER}"
value="${cmdInfo[cmd.name].url}" />
</div>
<div class="history-div">
<button>
<img src="icons/box-open-solid.svg"> View search history
</button>
${
cmdInfo[cmd.name].storeSearchHistory?
'<input type="checkbox" checked >'
:'<input type="checkbox" >'
}
<label><small>Save search history</small></label>
</div>
</div>
`
document.querySelector('#shortcuts').innerHTML += html;
try {
existingHistory = Boolean(cmdInfo[cmd.name].history.length)
} catch {
existingHistory = false;
}
div = document.getElementById(cmd.name);
div.querySelector('button').disabled = existingHistory;
// div.querySelector('.store-search-history').checked = cmdInfo[cmd.name].storeSearchHistory;
});

Angular 1 ng-if not displaying div

I've been writing a code that uses ng-if to display a div with a message if an array is empty([]). The ng-if isn't displaying the div even though I have console.log the array and it shows up empty.
I am still new to angularjs so I am not sure if I am using the ng-if directive correctly. Here is my code, anything helps, thank you!
js:
(function () {
'use strict';
var data = [];
var shoppingList = [
{
name: "Donuts",
quantity: "10"
},
{
name: "Cookies",
quantity: "10"
},
{
name: "Drinks",
quantity: "10"
},
{
name: "Shrimp",
quantity: "10"
},
{
name: "Ice Cream tub",
quantity: "100"
}
];
console.log(data);
angular.module('shoppingListCheckOffApp', [])
.controller('toBuyListController', toBuyListController)
.controller('boughtListController', boughtListController)
.service('shoppingListService', shoppingListService);
toBuyListController.$inject = ['shoppingListService'];
function toBuyListController(shoppingListService) {
var buy = this;
buy.shoppingList = shoppingList;
buy.shoppingListBought = function (itemIndex) {
shoppingListService.dataTransfer(buy.shoppingList[itemIndex].name, buy.shoppingList[itemIndex].quantity);
shoppingListService.remove(itemIndex);
};
}
boughtListController.inject = ['shoppingListService'];
function boughtListController(shoppingListService) {
var bought = this;
bought.data = shoppingListService.getData();
console.log(bought.data);
}
function shoppingListService() {
var service = this;
service.dataTransfer = function (itemName, quantity) {
var item = {
name: itemName,
quantity: quantity
};
data.push(item);
}
service.remove = function (itemIndex) {
shoppingList.splice(itemIndex, 1);
};
service.getData = function () {
return data;
};
};
})();
html:
<!doctype html>
<html ng-app="shoppingListCheckOffApp">
<head>
<title>Shopping List Check Off</title>
<meta charset="utf-8">
<script src="angular.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div>
<h1>Shopping List Check Off</h1>
<div>
<!-- To Buy List -->
<div ng-controller="toBuyListController as buy">
<h2>To Buy:</h2>
<ul>
<li ng-repeat="item in buy.shoppingList">Buy {{item.quantity}} {{item.name}}(s)<button
ng-click="buy.shoppingListBought($index);" ng-click="myVar = true"><span></span>
Bought</button></li>
</ul>
<div ng-if="buy.shoppingList === []">Everything is bought!</div>
</div>
<!-- Already Bought List -->
<div ng-controller="boughtListController as bought">
<h2>Already Bought:</h2>
<ul>
<li ng-repeat="item in bought.data">Bought {{item.quantity}} {{item.name}}(s)</li>
</ul>
<div ng-if="bought.data === []">Nothing bought yet.</div>
</div>
</div>
</div>
</body>
</html>
You should use ng-if (for arrays) in this way:
<div ng-if="!bought.data.length">Nothing bought yet.</div>
This will show the message when the list is empty.
If you do this:
buy.shoppingList === []
You are comparing you buy.shoppingList array with a new empty array, then it will return false.

Add item to array Angular

I have a table with these fields: product, lot, input1, input2. You can clone a line, and you can add a new line.
What I want to do is that for each row you can add a new Lot created by a "number" and by "id" that user write in the input field under the Select lot. And I wanted that the script add the new Lot in the json data and the lot 's option list.
This is the function for add that I tried to do:
$scope.addLot = function() {
var inWhichProduct = row.selectedProduct;
var newArray = {
"number": row.newLot.value,
"id": row.newLot.id
};
for (var i = 0; i < $scope.items.length; i++) {
if ($scope.items[i].selectedProduct === inWhichProduct) {
$scope.items[i].selectedLot.push(newArray);
}
}
};
-->> THIS <<-- is the full code.
Can you help me?
I think your question is a little too broad to answer on Stack Overflow, but here's an attempt:
<div ng-app="myApp" ng-controller="myCtrl">
<table>
<tr ng-repeat="lot in lots">
<td>{{ lot.id }}</td>
<td>{{ lot.name }}</td>
</tr>
</table>
<p>name:</p> <input type="text" ng-model="inputName">
<p>id:</p> <input type="text" ng-model="inputId">
<button ng-click="addLotButton(inputId, inputName)">Add</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.2/angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.lots = [{
name: "test",
id: 1
},
{
name: "test2",
id: 2
}
];
$scope.addLot = function(lotId, lotName) {
var newLotObject = {
name: lotName,
id: lotId
};
$scope.lots.push(newLotObject);
};
$scope.addLotButton = function(id, name) {
$scope.addLot(id, name);
};
$scope.addLot(3, "Another test");
});
</script>
Basically this code just takes some input and adds an object to the scope for that input. The table is created using an ng-repeat of this data. It's not great code at all but it's just a quick example.
The push method adds newArray to selectedLot array. It's not working on the JSON data but on arrays. If you want to have the JSON, you can give a try to :
var myJsonString = JSON.stringify(yourArray);
It will create a JSON string based on the parameter
Maybe you should try to structure your data to make lots as properties of products.
{
products: [
{id: 1, lots: [{id:1}, {id:2}]},
{id: 2, lots: [{id:1}, {id:2}]}
]
}
To add a lot to a product :
product = products[0];
product.lots.push(newArray);
Change the fallowing:
html:
<button ng-click="addLot(row.selectedProduct.id,row.newLot.value,row.newLot.id)">Add</button>
js:
$scope.addLot = function(id,val,lotId) {
// console.log(id);
var inWhichProduct = id;
var newArray = { "value": val, "id": lotId };
//console.log($scope.items)
angular.forEach($scope.items,function(v,i){
if($scope.items[i].id == id )
{
$scope.items[i].lots.push(newArray);
console.log($scope.items[i].lots);
}
});
};
http://plnkr.co/edit/W8eche8eIEUuDBsRpLse?p=preview

Item can't be moved after destination list gone empty once, how can I fix it?

See the plnkr http://plnkr.co/edit/atoDX2TqZT654dEicqeS?p=preview
How to move item from the list to the another empty list. Currently an item can't be moved once the destination list gone empty... How I can fix this for my application?
Here is the code sniped on tags for my application:
<div class="row">
<div class="span4 offset2" style="overflow-y:auto; height:150px;">
<ul ui-sortable="sortableOptions" ng-model="allDiagnosisFromDb" id="sourceList" ng-class="{'minimalList':sourceEmpty()}" class="connector">
<li class="alert alert-danger nomargin" ng-repeat="item in allDiagnosisFromDb">{{item.Name}}</li>
</ul>
</div>
<div class="span4" style="overflow-y:auto; height:150px; background-color:lightgray">
<ul ui-sortable="sortableOptions" id="targetList" ng-model="model" ng-class="{'minimalList':sourceEmpty()}" class="connector">
<li class="alert alert-info nomargin" ng-repeat="item in model">{{item.Name}}</li>
</ul>
</div>
</div>
code on angularjs controller:
function loadAllDiagnosis() {
$scope.allDiagnosisFromDb = [];
diagnosisPreferanceService.getAllDiagnosis()
.success(function (data) {
$scope.allDiagnosisFromDb = data;
})
.error(function (xhr) {
alert('error');
});
}
// init
$scope.model = [
{
"Id": 23,
"Name": "First tem."
}
];
$scope.sortableOptions = {
connectWith: '.connector'
}
// watch, use 'true' to also receive updates when values
// change, instead of just the reference
$scope.$watch("model", function (Name) {
console.log("Model: " + Name.map(function (e) { return e.Id }).join(','));
}, true);
// watch, use 'true' to also receive updates when values
// change, instead of just the reference
$scope.$watch("allDiagnosisFromDb", function (Name) {
console.log("allDiagnosisFromDb: " + Name.map(function (e) { return e.Id }).join(','));
}, true);
$scope.sourceEmpty = function () {
return $scope.allDiagnosisFromDb.length == 0;
}
$scope.modelEmpty = function () {
return $scope.model.length == 0;
}
Thanks in advance,,,,,,,,,:)
You can refer the below link exactly how you want it to be.
http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/simple
angular.module("demo").controller("SimpleDemoController", function($scope) {
$scope.models = {
selected: null,
lists: {"A": [], "B": []}
};
// Generate initial model
for (var i = 1; i <= 3; ++i) {
$scope.models.lists.A.push({label: "Item A" + i});
$scope.models.lists.B.push({label: "Item B" + i});
}
// Model to JSON for demo purpose
$scope.$watch('models', function(model) {
$scope.modelAsJson = angular.toJson(model, true);
}, true);
});

Categories

Resources