Loop through all children of in a firebase database key - javascript

i have a webapp where i save some values from inputs to the firebase database with this line:
fire.database().ref('gamehomeitems').push( dataset );
the dataset includes a "category", "value1" and "value2".
on another page, i want to render all the children saved in the 'gamehomeitems' part of my firebase database, but im not able to loop through them and get their values
what would be the appropriate code to render the category of all the children in 'gamehomeitems'?
Thanks in advance for any help

This question has been asked many times before and is covered in the documentation for Working with Lists of Data. But here is a bundled example of one way to achieve what you want.
Assuming this is your table:
<table style="width:100%" id="gamehomeitems-table">
<tr id="gamehomeitems-headerrow">
<th>Category:</th>
<th>Home Team:</th>
<th>Away Team:</th>
</tr>
</table>
<!-- at the bottom of the body -->
<script src="https://www.gstatic.com/firebasejs/8.2.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.2.1/firebase-database.js"></script>
<script>
firebase.initializeApp(/* ... */);
const gameHomeItemsRef = firebase.database().ref("gamehomeitems");
const gameHomeItemsTbl = document.getElementById("gamehomeitems-table");
const gameHomeItemsQuery = gameHomeItemsRef.orderByKey().limitToLast(20); // get 20 most recent entries
const gameHomeItemsChildAddedCallback =
gameHomeItemsQuery
.on('child_added', function(snapshot, keyOfPreviousRow) {
const rowData = snapshot.val();
let rowContent = '<tr id="item-' + snapshot.key + '">';
rowContent += "<td>" + rowData.category + "</td>";
rowContent += "<td>" + rowData.value1 + "</td>";
rowContent += "<td>" + rowData.value2 + "</td>";
rowContent += "</tr>";
gameHomeItemsTbl.append(rowContent);
// todo: make sure this row is inserted above the row for "keyOfPreviousRow" if newest at the top is required.
// currently it will be oldest at the top, newest at the bottom
});
const gameHomeItemsChildChangedCallback =
gameHomeItemsQuery
.on('child_changed', function(snapshot, keyOfPreviousRow) {
// todo: find row with id "item-KEY" and update it's data in the table
});
const gameHomeItemsChildRemovedCallback =
gameHomeItemsQuery
.on('child_removed', function(snapshot) {
// todo: find row with id "item-KEY" and remove it from the table
});
// later, when you no longer need the table to be updated live
// gameHomeItemsRef.off("child_added", gameHomeItemsChildAddedCallback);
// gameHomeItemsRef.off("child_changed", gameHomeItemsChildChangedCallback);
// gameHomeItemsRef.off("child_removed", gameHomeItemsChildRemovedCallback);
// todo: implement "child_moved" when not using orderByKey()
</script>

Related

How to fix passing in data from api to display correctly in a table?

I am trying to gather the data I collect from the API crypto compare and display into a table. I am able to generate the and append them to the table body. I keep running into this weird problem where every time I iterate with a for loop each individual data for the coin doesn't go into each row but instead places all the data, all 100 into 1 row.
When I assign I to any number the table has no problem showing 1 coin, which then takes up 1 row like it's supposed too.
I have tried assigning the class names to variables where I would append the data to the variable of the classes that didn't work.
for (let i = 0; i < $marketCapNumber; i++) {
$('.a').append(
"<tr class='tableRowData'>" +
"<td class='rank data' id = '1'> </td>" +
"<td class='name data' id = '2'> </td>" +
"<td class=' symbol data' id= '3'> </td>" +
"<td class=' marketCap data' id ='4'> </td>" +
"<td class='price data' id='5'> </td>" +
"</tr>"
);
}
//data from the API
for (let j = 0; j < 100; j++) {
// Name
let name = data.Data[j].CoinInfo.FullName;
// symbol e.g btc, xrp, ltc
let symbol = data.Data[j].DISPLAY.USD.FROMSYMBOL;
// price
let price = data.Data[j].DISPLAY.USD.PRICE;
// marketcap
let $marcketCap = data.Data[j].DISPLAY.USD.MKTCAP;
// created inputs
const $nameOfCoin = $('<p>').text(`${name}`);
const $ticker = $('<p>').text(`${symbol}`);
const $coinprice = $('<p>').text(`${price}`);
const $totalMarketCap = $('<p>').text(`${$marcketCap}`);
// assigning variable to class names
const nameClass = $('.name');
const symbolClass= $('.symbol');
const priceClass = $('.price');
const marketCapClass = $('.marketCap');
// append to the <td>
$(nameClass).append($nameOfCoin);
$(symbolClass).append($ticker);
$(priceClass).append($coinprice);
$(marketCapClass).append($totalMarketCap);
}
I am expecting to iterate through each coin and add that coins info to one row of data, instead its adding the entire list of coins to 1 row for each row. Whenever I take away the for loop and just assign it a number it will place the coins info in the row individually. How can I fix this since I'm trying to pass in each coin that corresponds with the array and not just showcase one number 100 times?
Once the table is created and you do this $(priceClass).append($coinprice); that's grabbing every single instance of <td class='price data' id = '5'> </td> in the table and appending the value of $coinprice to every single one of them. In the end if I had an array of 5 coins 1 - 5 I'd expect to see this <td class='price data' id='5'><p>1</p><p>2</p><p>3</p><p>4</p><p>5</p></td> for every row of the table.

Why does the array repeat the entered data from first to last

I'm having trouble with my code. I build this code but there is an issue that I cannot resolve myself. The code should work like this: When entering multiple data (name & email) the datas repeat from top to last.
For example I enter 3 names & emails one by one. I want an output of
Fred fred#gmail.com
George george#gmail.com
Laila laila#gmail.com
But instead I get this results in my table:
Fred fred#gmail.com
Fred fred#gmail.com
George George#gmail.com
Fred fred#gmail.com
George George#gmail.com
Laila laila#gmail.com
In the clearAndSave method in the end when you call $("#output").append(html); you should call $("#output").empty(); first to clear the previous results.
Change the method like this:
function clearAndSave() {
//...
$("#output").empty();
$("#output").append(html);
}
If you want to presist your initial data, modify the clearAndSave method like this:
function clearAndSave() {
// Clear fields
nameInput.value = "";
emailInput.value = "";
var html = [];
console.log(arraypeaople);
for(i = 0; x <= arraypeaople.length - 1; i++){
// Mark added rows to be able to remove them later
html += "<tr class='added-row'>";
html += "<td>" + arraypeaople[i].name + "</td>";
html += "<td>" + arraypeaople[i].email + "</td>";
html += "</tr>";
}
// Remove just the added rows
$("#output").find(".added-row").remove();
$("#output").append(html);
}

Filtered JSON data in mulitple HTML tables with Javascript

I have a JSON file and I am trying to return multiple HTML tables depending on the values of some columns in the JSON.
At the moment I have the following working. More specifically, it loads the JSON values into a table without any filters applying.
var data = {"headers":["plat","chan","group","03","cat","05","06","07","08","09","10","11","12","13","14","15","16","17"],"rows":[["plat1","chan1","aaaa","xxxxx","cat1","yyyy",133,236,0,"656",0,956,37,36,12,67,1],
["plat1","chan1","aaaa","xxxxx","cat2","yyyy",178,867,0,"656",0,647,39,12,18,65,2],
["plat1","chan1","bbb","xxxxx","cat1","yyyy",378,867,0,"656",0,350,32,97,19,64,3],
["plat1","chan1","bbb","xxxxx","cat2","yyyy",137,167,0,"656",0,523,46,86,32,62,4],
["plat2","chan1","aaaa","xxxxx","cat1","yyyy",133,236,0,"656",0,956,37,36,12,67,1],
["plat2","chan1","aaaa","xxxxx","cat2","yyyy",178,867,0,"656",0,647,39,12,18,65,2],
["plat2","chan1","bbb","xxxxx","cat1","yyyy",378,867,0,"656",0,350,32,97,19,64,3],
["plat3","chan1","bbb","xxxxx","cat2","yyyy",137,167,0,"656",0,523,46,86,32,62,4]]};
string = JSON.stringify(data);
//AAA Table + cat1
var table1 = '<div class="row"><div class="col-lg-6" style="background-color: #e90649; width: 117px;"> </div><div class="col-lg-6" style="max-width: 100px; padding-left: 10px; font-size: 2vw;">AAAA<br/><br/><span style="font-size: 1vw;">Cat1</span><br/><span style="font-size: 0.8vw; color: #ccc; font-weight: normal;">07 Jul 2017 - 18 Jul 2017</span></div><div class="col-lg-6"><div class="container"><table><thead><tr><th>plat</th><th>chan</th><th>03</th><th>05</th><th>06</th><th>07</th><th>08</th></tr></thead><tbody>';
$.each(data.rows, function(i) {
table1 +="<tr><td>" + data.rows[i][0] + "</td><td>" + data.rows[i][1] + "</td><td>" + data.rows[i][6] + "</td><td>" + data.rows[i][7] + "</td><td>" + data.rows[i][8] + "</td><td>" + data.rows[i][10] + "</td><td>" + data.rows[i][9] + "</td></tr>";
});
table1 += '</tbody></table></div></div></div>';
$("#one").html(table1);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="one"></div>
Combining the values of three columns, I have three different categories. For each category, JS will return an HTML table but with summed rows. For example, we have 2 rows for a combo of plat1 && chan1 && bbb but in the filtered table, I want to see 1 row with the numbers of the columns summed. As a start, I am trying to filter the JSON and create one table and I am stuck (I will update the question with any problems related to the summing of the numbers etc).
var data = {"headers":["plat","chan","group","03","cat","05","06","07","08","09","10","11","12","13","14","15","16","17"],"rows":[["plat1","chan1","aaaa","xxxxx","cat1","yyyy",133,236,0,"656",0,956,37,36,12,67,1],
["plat1","chan1","aaaa","xxxxx","cat2","yyyy",178,867,0,"656",0,647,39,12,18,65,2],
["plat1","chan1","bbb","xxxxx","cat1","yyyy",378,867,0,"656",0,350,32,97,19,64,3],
["plat1","chan1","bbb","xxxxx","cat2","yyyy",137,167,0,"656",0,523,46,86,32,62,4],
["plat2","chan1","aaaa","xxxxx","cat1","yyyy",133,236,0,"656",0,956,37,36,12,67,1],
["plat2","chan1","aaaa","xxxxx","cat2","yyyy",178,867,0,"656",0,647,39,12,18,65,2],
["plat2","chan1","bbb","xxxxx","cat1","yyyy",378,867,0,"656",0,350,32,97,19,64,3],
["plat3","chan1","bbb","xxxxx","cat2","yyyy",137,167,0,"656",0,523,46,86,32,62,4]]};
string = JSON.stringify(data);
var table1 = '';
$.each(data.rows, function(i) {
//JSON to string for the Regex check
if(JSON.stringify(data.rows[i][0]).match(/plat1/) && JSON.stringify(data.rows[i][4]).match(/cat1/) && JSON.stringify(data.rows[i][2]).match(/bbb/))
{
table1 += '<div class="row"><div class="col-lg-6" style="background-color: #e90649; width: 117px;"> </div><div class="col-lg-6" style="max-width: 100px; padding-left: 10px; font-size: 2vw;">BBB<br/><br/><span style="font-size: 1vw;">Cat1</span><br/><span style="font-size: 0.8vw; color: #ccc; font-weight: normal;">07 Jul 2017 - 18 Jul 2017</span></div><div class="col-lg-6"><div class="container"><table><thead><tr><th>plat</th><th>chan</th><th>03</th><th>05</th><th>06</th><th>07</th><th>08</th></tr></thead><tbody>';
$.each(data.rows, function(i)
{
table1 +="<tr><td>" + data.rows[i][0] + "</td><td>" + data.rows[i][1] + "</td><td>" + data.rows[i][6] + "</td><td>" + data.rows[i][7] + "</td><td>" + data.rows[i][8] + "</td><td>" + data.rows[i][10] + "</td><td>" + data.rows[i][9] + "</td></tr>";
});
table1 += '</tbody></table></div></div></div>';
};
});
$("#one").html(table1);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="one"></div>
I am trying to think of the best way doing that. I will definitely need a loop in order to check a) How many different combinations I have, b) To create the table in the HTML, c) To create the subtable that shows the JSON data.
Like I said in the comments I think a nicer approach is to transform the raw data to a more usable format, and then have separate logic to display the tables. Here I have an example of how to transform the data so that each row knows about the association between the header name and the data.
When the data is in the right format, it becomes easier to see how you would, for example, sum the values in one column (sum values associated with a specific header name). I've included an example of that as well.
You can also see how I divide a big problem like printing a table, in smaller steps (getting the table header, getting ONE table row). Then I combine these smaller functions to get the wanted behavior.
For data transformation it's very useful to get to know the Array methods, like .map, .forEach and .reduce. I have examples of each of them. Mozilla have good documentation of these methods (see above).
I hope this helps you see how you could continue breaking down the problem until you have all the functionality you wanted. Feel free to ask me if you have further questions!
EDIT: The integrated code here in SO is bit hard to work with, so I have a JSFiddle demo you could see here: https://jsfiddle.net/jonahe/jLnph69s/
EDIT 2: New JSFiddle demo Now with a printed example of sums:
https://jsfiddle.net/jonahe/ntmg68dp/ As you can see, it relies heavily on reusing the smaller functions from before.
var data = {"headers":["plat","chan","group","03","cat","05","06","07","08","09","10","11","12","13","14","15","16","17"],"rows":[["plat1","chan1","aaaa","xxxxx","cat1","yyyy",133,236,0,"656",0,956,37,36,12,67,1],
["plat1","chan1","aaaa","xxxxx","cat2","yyyy",178,867,0,"656",0,647,39,12,18,65,2],
["plat1","chan1","bbb","xxxxx","cat1","yyyy",378,867,0,"656",0,350,32,97,19,64,3],
["plat1","chan1","bbb","xxxxx","cat2","yyyy",137,167,0,"656",0,523,46,86,32,62,4],
["plat2","chan1","aaaa","xxxxx","cat1","yyyy",133,236,0,"656",0,956,37,36,12,67,1],
["plat2","chan1","aaaa","xxxxx","cat2","yyyy",178,867,0,"656",0,647,39,12,18,65,2],
["plat2","chan1","bbb","xxxxx","cat1","yyyy",378,867,0,"656",0,350,32,97,19,64,3],
["plat3","chan1","bbb","xxxxx","cat2","yyyy",137,167,0,"656",0,523,46,86,32,62,4]]};
// transform the data to get a clear connection between the
// heading and the corresponding data
const transformedData = data.rows.map((row) => {
const emptyRowDataObject = {};
return row.reduce((dataObjSoFar, rowData, rowDataIndex) => {
// for each of the values in the row, add a property
// with the name of the corresponding header
const correspondingHeader = data.headers[rowDataIndex];
dataObjSoFar[correspondingHeader] = rowData;
return dataObjSoFar;
}, emptyRowDataObject);
});
const headersOfInterest = ['plat', 'chan', '03', '05', '06', '07', '08'];
printTable(headersOfInterest, transformedData);
console.log('sum of column 06 is: ' , getSumOfValuesInColumn('06', transformedData));
console.log('transformed data looks like', transformedData);
function printTable(headers, rowDataWithHeaders) {
let tableHeader = createTableHeaders(headers);
let tableRows = rowDataWithHeaders.map(row => createTableRow(headers, row));
let table = `<table>${ tableHeader }<tbody>${ tableRows }</tbody></table>`;
$("#one").html(table);
}
function createTableHeaders(headers) {
let headersHTML = '<thead><tr>';
headers.forEach(header => {
headersHTML += `<th>${ header }</th>`;
});
headersHTML += '</tr></thead>';
return headersHTML;
}
function createTableRow(headers, dataRow) {
let tr = '<tr>';
// go through all the headers we are interested in
// and get the corresponding value from this data row
headers.forEach(header => {
tr += `<td>${ dataRow[header] }</td>`;
});
tr += '</tr>';
return tr;
}
function getSumOfValuesInColumn(headerName, rowDataWithHeaders) {
// this could be done with Array.reduce as well
let sum = 0;
for(let i = 0; i < rowDataWithHeaders.length; i++) {
sum += rowDataWithHeaders[i][headerName]
}
return sum;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="one"></div>

javascript : built an html form from json, but can't update the form

I have a javascript code that takes objects from json.
from this, i built an html string:
var htmlstr = "<table border=0>";
for (var i=0;i<jsonData.people.length;i++) {
htmlstr=htmlstr+"<tr><td>" + jsonData.people[i].name + "</td>";
htmlstr=htmlstr+"<td>"+ jsonData.people[i].cash + "</td>";
htmlstr=htmlstr+"<td><button onclick='changeCash(i)'>Update</button></td></tr>";
}
htmlstr=htmlstr+"</table>";
layer.addFeatures(features);
layer.events.on({ "featureselected": function(e) { updateMak('mak', htmlstr) } });
function changeCash(k) {
jsonData.people[k].cash=jsonData.people[k].cash+100;
}
The HTML page is as follows:
<script type="text/javascript">
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
alert("Mobile device detected."); }
function updateMak(id,content) {
var container = document.getElementById(id);
container.innerHTML = content;
} </script>
<div id="mak"> List of People </div>
Lets say this displays 10 people with their money.
If I click on one of their Update buttons, I think the json data is updated as intended. But I don't know how to verify it. The values in the form doesn't update the new value from the changeCash function.
How do I update the htmlstr and also update what's already displayed on screen?
Please advise.
When you generate htmlstr for the people cash
htmlstr=htmlstr+"<td>"+ jsonData.people[i].cash + "</td>";
You should also generate id for this td so that you can update the content from the function changeCash(k).
Something like
htmlstr=htmlstr+"<td id='peoplecash"+i+"'>" + jsonData.people[i].cash + "</td>";
And then in your changeCash function
function changeCash(k) {
jsonData.people[k].cash=jsonData.people[k].cash+100;
var peoplecash= document.getElementById("peoplecash"+k);
peoplecash.innerHTML = jsonData.people[k].cash;}

jquery adding columns based on database records

I have an sqlite table with these columns:
| date | weight | bmi | mood | etc.
I want a table on my html page to display like this on the html page:
<table>
<caption></caption>
<thead>
<tr>
<td>(empty cell over row headings)</td>
Additional tH's as needed (this is where each date entry goes)
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Weight</th>
additional tD's as needed (this is where each weight entry goes matched with date in column heading)
</tr>
<tr>
<th scope="row">BMI</th>
additional tD's as needed (same as above)
</tr>
</tbody>
</table>
so basically I'm flipping the rows and columns for display purposes. This is all so I can graph the table using jQuery Visualize plugin that goes out as the date progresses. As you can imagine, over time more entries will be made adding to the columns of the display table. Here is what I have been messing around with so far (not including the graphing scripts ). I've gotten myself totally confused and now I'm just a mess...
Any suggestions would be a big help. I think I'm running into problems when trying to insert data into a table that's also trying to insert itself. I'm probably going about this wrong I bet.
Thanks
Mike
function homeSuccess(tx, results) {
// Gets initial count of records in table...
var entries = results.rows.length;
// Iterates over all the existing records...
for (var i = 0; i < entries; ++i) {
// The following element id's can be found in the div's within the table below, see element.innerHTML line...
var element = document.getElementById('colDate');
element.innerHTML += '<th scope="col">' + results.rows.item(i).timeStamp + '</th>';
var element2 = document.getElementById('tdWeight');
element2.innerHTML += '<td>' + results.rows.item(i).weight + '</td>';
var element3 = document.getElementById('tdBmi');
element3.innerHTML += '<td>' + results.rows.item(i).bmi + '</td>';
};
// 'screenView2 is a placeholder on the main html page...
var element = document.getElementById('screenView2');
element.innerHTML = '<br /><br /><h1>Data:</h1><br />Number of entries: ' + entries + '<br />' + '<table><caption>Mikes Health</caption><thead><tr><td></td><div id="colDate"></div></tr></thead><tbody><tr><th scope="row">Weight</th><div id="colWeight"></div></tr><tr><th scope="row">BMI</th><div id="colBmi"></div></tr></tbody></table>';
// This section is just a test trying to plug in static elements prior to trying database data... When using this section I had the iteration section commented out.
var element2 = document.getElementById('colDate');
element2.innerHTML = '<th scope="col">4-1-13</th>';
var element3 = document.getElementById('colWeight');
element3.innerHTML = '<td scope="col">123</td>';
var element4 = document.getElementById('colBmi');
element4.innerHTML = '<td scope="col">321</td>';
}
function homeQuery(tx) {
console.log("entering homeQuery");
tx.executeSql('SELECT * FROM HEALTHGRAPH', [], homeSuccess, onSqlError);
console.log("leaving homeQuery");
}
// Function that is called on initial page load
function homeDBopen() {
console.log("opening db for home data");
theDB = window.openDatabase("hgDB", "1.0", "HealthGraph", 3 * 1024 * 1024);
theDB.transaction(homeQuery, onTxError, onTxSuccess);
console.log("leaving homeDBopen");
}
Thought for sure someone would have answered this question as it seems like an issue lots of people must run into. A little discouraging. Anyway, I found an answer that I can adapt to my own project here:
http://msdn.microsoft.com/en-us/library/ie/ms532998(v=vs.85).aspx
// Insert cells into the header row.
for (i=0; i<heading.length; i++)
{
oCell = oRow.insertCell(-1);... etc.

Categories