Push/update array from JavaScript to HTML - javascript

I have made a array of data from Firebase, and want to display it on my website. It works fine one time, but when Firebase is updated, the website doesn´t update correspondingly.
My goal is to make a list of updates. So when the database is updated, the new update is shown above the previous.
console.log(arr); logs every change made in the database, so basically I want what the console displays..
JS code:
firebase.initializeApp(config);
database = firebase.database();
var ref = database.ref("users");
ref.on("value", gotData, errData);
function gotData(data) {
// console.log(data.val);
var users = data.val();
var keys = Object.keys(users);
//console.log(keys);
for (var i = 0; i < keys.length; i++) {
var k = keys [i];
var name = users [k].Name;
var gender = users [k].Gender;
var car = users [k].Car;
var location = users [k].Location;
var destination = users [k].Destination;
// initialize array
var arr = [
name,
gender,
car,
location,
destination,
];
// append new value to the array
arr.push(destination);
document.getElementById('B1').innerHTML = JSON.stringify(arr);
console.log(arr);
}
}
function errData(err) {
console.log("Error");
console.log(err);
}
<!DOCTYPE html
<html>
<head
<meta charset="utf-8">
<title>Test</title>
<script src="https://www.gstatic.com/firebasejs/live/3.1/firebase.js"></script>
</head>
<body>
Test
<!-- Value -->
<ol id="B1"></ol>
<script src ="App.js"></script>
</body>
</html>
Firebasestructure:
App
users
09IEbFijEnQpDita5DyhUdBE0eD3
Name: "Nick"
Car: "Audi"
Gender: " Male"
Location: "Home"
Destination: " Beach"
Is there a good (and hopefully not to complicated) way to reach my goal?
Thank you.

You are resetting your array in every iteration, while you really want to keep the data from the previous iterations in there. So intitialise your array before entering the loop, and only add to it within the loop. In the same way you overwrite the output in the HTML element in each iteration. Instead, accumulate the data in the loop and only output the array after the loop:
function gotData(data) {
var users = data.val();
var keys = Object.keys(users);
// initialize array here
var arr = [];
for (var i = 0; i < keys.length; i++) {
var k = keys[i];
var name = users[k].Name;
var gender = users[k].Gender;
var car = users[k].Car;
var location = users[k].Location;
var destination = users[k].Destination;
// append new value to the array
arr.push([
name,
gender,
car,
location,
destination,
]);
}
// And now output:
document.getElementById('B1').innerHTML = JSON.stringify(arr);
console.log(arr);
}
All this can be done a bit shorter with the use of Object.values (assuming you want all the data fields):
function gotData(data) {
var arr = Object.values(data.val()).map(Object.values);
document.getElementById('B1').innerHTML = JSON.stringify(arr);
console.log(arr);
}
If you want the last value at the top of the output then use the reverse method, and if you want it in a list format then map the values to li tags. Finally, you may want to limit the number of rows to some constant (e.g. 10), which you can do with slice:
function gotData(data) {
var arr = Object.values(data.val()).map(Object.values);
B1.innerHTML = arr.slice(-10).reverse().map(val => `<li>${val}</li>`).join('');
}
Note that you don't really need document.getElementById nowadays, since browsers declare global variables for each of the elements with an id attribute. So you can just use the B1 variable.

Related

How to select specified data like id in a for loop to use those data in different page

I want to get and store id from idArray to use each id indvidual
I tried to store in session storage but it return the last element
success: function (data) {
const myText = "";
const addressArray = [];
const titleArray = [];
const typeArray = [];
const idArray = [];
data.map((user) => {
addressArray.push(user.address);
titleArray.push(user.title);
typeArray.push(user.jtype);
idArray.push(user.id);
});
container.innerHTML = "";
for (let i = 0; i <= 3; i++) {
let clone = row.cloneNode(true);
container.appendChild(clone);
container.firstChild.innerHTML = "";
jobtitle.innerHTML = data[i].title;
jbtype.innerHTML= typeArray[i];
jbaddress.innerHTML= addressArray[i];
sessionStorage.setItem('jobid',idArray[i]);
}
}
The issue I can see is , since the key is always same , it is overriding the value of the same key.
You can instead do something like
sessionStorage.setItem("jobid-"+i,idArray[i]);
This should solve the problem for sure.
It returns the last value because you are using the same key to store each value. Try using a different key for each or alternately, create an array of ids using map function and store the array in session with the key 'jobid'.
You can serialize and store it in session as follows:
sessionStorage.setItem('jobid', JSON.stringify(idArray));
To read the same back out you can use code like
JSON.parse(sessionStorage.getItem('jobid'));

looping through collection of javascript objects

Am trying to read only very first element of friends array and add it to matches array for each object. If I add matches property directly on object. Then it returns expected result. But if I use a function addmatches to add matches array property. Then matches array value is coming same for each animal object.
var AnimalCreator = function(username, species, tagline, noises) {
var friends = [];
//var matches = [];
return {
username: username,
species: species,
tagline: tagline,
noises: noises,
friends: friends,
//matches: matches
}
};
var sheep = AnimalCreator('Cloud', 'sheep', 'You can count on me!', ['baahhh', 'arrgg', 'chewchewchew']);
var rabbit = AnimalCreator('Sky', 'Rabbit', 'I like jumping!', ['haha', 'heehee']);
var tiger = AnimalCreator('Tim', 'Tiger', 'I am strong!', ['Grrrr', 'grrrrrr!']);
var bear = AnimalCreator('Poo', 'Bear', 'I am your friend', ['wowo', 'whwhwh']);
var addFriend = function(animal, friend) {
animal.friends.push(friend.username);
};
addFriend(sheep, rabbit);
addFriend(sheep, tiger);
addFriend(tiger, bear);
var myFarm = [sheep, rabbit, tiger, bear];
var addmatches = function(farm){
var matches = [];
for(var i=0;i < farm.length; i++){
farm[i].matches = matches;
}
};
addmatches(myFarm);
var giveMatches = function(farm) {
for (var i = 0; i < farm.length; i++) {
if (farm[i].friends.length > 0) {
farm[i].matches.push(farm[i].friends[0]);
}
}
};
giveMatches(myFarm);
console.log(myFarm);
matches is a reference to an empty array and your code is assigning same reference for every farm object ( farm[i].matches = matches; ), you can try by assigning empty array directly like
farm[i].matches = [];
Your commented code: The function AnimalCreator is creating a new array instance on every call and every animal object is referencing to a unique array, that's why when you directly add matches, it works as expected.
Hope this will help!
This is because array is passed by referance, so every farm object is pointing to the same array by this "farm[i].matches = matches;". To fix this you can do multiple tihings.
Change "farm[i].matches = matches;" to "farm[i].matches = [];" (Best option as of now).
Move "var matches = [];" inside for loop and use "let" insted of "var".

Function output replaces first two rows of my main JSON string

I have a JSON query and I am using console.log to present it:
var json_data = {"headers":["Month","Value","Number"],"rows":[["2018-10-01 00:00:00.0","one",209],["2018-09-01 00:00:00.0","one",274],["2018-09-01 00:00:00.0","five",183],["2018-10-01 00:00:00.0","five",164],["2018-09-01 00:00:00.0","four",214],["2018-10-01 00:00:00.0","four",192],["2018-09-01 00:00:00.0","three",128],["2018-10-01 00:00:00.0","three",125],["2018-09-01 00:00:00.0","two",199],["2018-10-01 00:00:00.0","two",169],["2018-09-01 00:00:00.0","seven",10541],["2018-10-01 00:00:00.0","seven",6139],["2018-10-01 00:00:00.0","six",169],["2018-09-01 00:00:00.0","six",233]]};
document.getElementById("original").innerHTML = json_data.rows;
<div style="background:yellow; "id="original"></div>
<div style="background:red;" id="output"></div>
And for the value "one" I have two numbers (209 and 274).
I am then using a function to groupby which works fine (output). My problem is that when I use the console.log for the initial json_data query, the first two rows are different. It seems that my function replaced the first two rows with the rows of the output (red). The function is given here:
function initialGroupBy(rows) {
const
rowMap = new Map(),
result = [],
dataTemp = [];
// Iterate over the rows.
rows.forEach(row => {
const
// Create a key, it is the first elements joined together.
key = row.slice(0,1).join();
// Check if the Map has the generated key...
if (rowMap.has(key)) {
// The map has the key, we need to add up the values
const
// Get the value for the current key.
storedRow = rowMap.get(key);
// Add the value of the current row to the row in the map.
storedRow[2] += row[2];
} else {
// The key doens't exist yet, add the row to the map.
rowMap.set(key, row);
}
});
// Iterate over all the entries in the map and push each value with the
// summed up value into the array.
rowMap.forEach(value => {
result.push(value);
});
for (i = 0; i < result.length; i++)
{
var object2 = {"date": result[i][0].slice(0,7), "num": result[i][2]};
dataTemp.push(object2);
}
return dataTemp;
}
A full snippet can be found here (Compare the first two rows of the yellow box from the two snippets):
var json_data = {"headers":["Month","Value","Number"],"rows":[["2018-10-01 00:00:00.0","one",209],["2018-09-01 00:00:00.0","one",274],["2018-09-01 00:00:00.0","five",183],["2018-10-01 00:00:00.0","five",164],["2018-09-01 00:00:00.0","four",214],["2018-10-01 00:00:00.0","four",192],["2018-09-01 00:00:00.0","three",128],["2018-10-01 00:00:00.0","three",125],["2018-09-01 00:00:00.0","two",199],["2018-10-01 00:00:00.0","two",169],["2018-09-01 00:00:00.0","seven",10541],["2018-10-01 00:00:00.0","seven",6139],["2018-10-01 00:00:00.0","six",169],["2018-09-01 00:00:00.0","six",233]]};
function initialGroupBy(rows) {
const
rowMap = new Map(),
result = [],
dataTemp = [];
// Iterate over the rows.
rows.forEach(row => {
const
// Create a key, it is the first elements joined together.
key = row.slice(0,1).join();
// Check if the Map has the generated key...
if (rowMap.has(key)) {
// The map has the key, we need to add up the values
const
// Get the value for the current key.
storedRow = rowMap.get(key);
// Add the value of the current row to the row in the map.
storedRow[2] += row[2];
} else {
// The key doens't exist yet, add the row to the map.
rowMap.set(key, row);
}
});
// Iterate over all the entries in the map and push each value with the
// summed up value into the array.
rowMap.forEach(value => {
result.push(value);
});
for (i = 0; i < result.length; i++)
{
var object2 = {"date": result[i][0].slice(0,7), "num": result[i][2]};
dataTemp.push(object2);
}
return dataTemp;
}
const damn = initialGroupBy(json_data.rows);
document.getElementById("original").innerHTML = json_data.rows;
document.getElementById("output").innerHTML =JSON.stringify(damn);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="background:yellow; "id="original"></div>
<br><br>
<div style="background:red;" id="output"></div>
I have tried changing the var to const in many cases. Am I missing a fundamental JavaScript case here?
As your value is an Array object, when you save it in your temporary Map, you're actually using a reference to your original data structure row.
So in the first forEach loop, where you sum the values you're actually changing the original array entry.
The solution is pretty simple, just clone the array:
rowMap.set(key, row.slice());
Another possibility is to use a different array to save the totals.
Here is your code with the fix.
var json_data = {"headers":["Month","Value","Number"],"rows":[["2018-10-01 00:00:00.0","one",209],["2018-09-01 00:00:00.0","one",274],["2018-09-01 00:00:00.0","five",183],["2018-10-01 00:00:00.0","five",164],["2018-09-01 00:00:00.0","four",214],["2018-10-01 00:00:00.0","four",192],["2018-09-01 00:00:00.0","three",128],["2018-10-01 00:00:00.0","three",125],["2018-09-01 00:00:00.0","two",199],["2018-10-01 00:00:00.0","two",169],["2018-09-01 00:00:00.0","seven",10541],["2018-10-01 00:00:00.0","seven",6139],["2018-10-01 00:00:00.0","six",169],["2018-09-01 00:00:00.0","six",233]]};
function initialGroupBy(rows) {
const
rowMap = new Map(),
result = [],
dataTemp = [];
// Iterate over the rows.
rows.forEach(row => {
const
// Create a key, it is the first elements joined together.
key = row.slice(0,1).join();
// Check if the Map has the generated key...
if (rowMap.has(key)) {
// The map has the key, we need to add up the values
const
// Get the value for the current key.
storedRow = rowMap.get(key);
// Add the value of the current row to the row in the map.
storedRow[2] += row[2];
} else {
// The key doens't exist yet, add the row to the map.
rowMap.set(key, row.slice());
}
});
// Iterate over all the entries in the map and push each value with the
// summed up value into the array.
rowMap.forEach(value => {
result.push(value);
});
for (i = 0; i < result.length; i++)
{
var object2 = {"date": result[i][0].slice(0,7), "num": result[i][2]};
dataTemp.push(object2);
}
return dataTemp;
}
const damn = initialGroupBy(json_data.rows);
document.getElementById("original").innerHTML = json_data.rows;
document.getElementById("output").innerHTML =JSON.stringify(damn);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="background:yellow; "id="original"></div>
<div style="background:red;" id="output"></div>
A) The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable -> Link
B) Your problem is that you are actually editing the original object in the initialGroupBy function. Maybe this answer will be helpful.
A different logic applies here and the result is handy:
var json_data = {"headers":["Month","Value","Number"],"rows":[["2018-10-01 00:00:00.0","one",209],["2018-09-01 00:00:00.0","one",274],["2018-09-01 00:00:00.0","five",183],["2018-10-01 00:00:00.0","five",164],["2018-09-01 00:00:00.0","four",214],["2018-10-01 00:00:00.0","four",192],["2018-09-01 00:00:00.0","three",128],["2018-10-01 00:00:00.0","three",125],["2018-09-01 00:00:00.0","two",199],["2018-10-01 00:00:00.0","two",169],["2018-09-01 00:00:00.0","seven",10541],["2018-10-01 00:00:00.0","seven",6139],["2018-10-01 00:00:00.0","six",169],["2018-09-01 00:00:00.0","six",233]]};
function groupBy(accumulator, item) {
const [date,extra,value] = item;
const key = date.slice(0,7);
if(!accumulator[key]){
accumulator[key] = 0
}
accumulator[key] += value;
return accumulator;
}
var damn = json_data.rows.reduce(groupBy,{});
damn = Object.keys(damn).map(function(key){
return {date: key, Value: "Total", num: damn[key]};
})
document.getElementById("original").innerHTML = json_data.rows;
document.getElementById("output").innerHTML =JSON.stringify(damn);
<div style="background:yellow; "id="original"></div>
<div style="background:red;" id="output"></div>

Dexie.js iterating a dynamic list

I am using dexie.js, which is an indexDB wrapper. Anywhoo, I have an array that is called from the user's local storage, and my function is supposed to iterate through every list item in the DB and show it. However, upon clicking on my Butane it only shows the most recent input of name.
Note: You can see the entire database by adding a few values in and checking your local storage.
My JsFiddle:
https://jsfiddle.net/enzp3zws/1/
my html:
<ul id="mane"></ul>
my js:
var db = new Dexie("TestDatabase");
db.version(1).stores({
friends: '++id, name, age'
});
var collection = db.friends;
var placement = document.getElementById('rainman');
var jacement = document.getElementById('rainboy');
var stacement = document.getElementById('mane');
var listed = document.createElement('li');
function addrain(){
collection.each(function(friend){
var element = [friend.name];
for (var i = 0; i < element.length; i++){
listed.textContent = element[i];
document.getElementById('mane').appendChild(listed);
//alert(element); <-- this call alerts all names in database.
}
});
}
Please excuse the randomness of some of these variable names. I don't know what sleep is anymore.
You need to create a new 'li' element each time:
//Remove var listed = ... line in header, then:
function addrain(){
collection.each(function(friend){
var element = [friend.name];
for (var i = 0; i < element.length; i++){
var listed = document.createElement('li');
listed.textContent = element[i];
document.getElementById('mane').appendChild(listed);
}
//alert(element); <-- this call alerts all names in database.
});
}
The reason your code did not work before is that you only created one li element, and repeatedly changed its text and re-inserted it at different locations.

How do I copy a foundset?

So I have the following issue:
I have a Foundset with a bunch of records, and I'd like to (deep) copy them to a new location, including all values but without the IDs. What's the best way to do this?
If you want to do an deep copy of an foundset you need the follow steps:
Create an empty foundset over retrieveOrCreateFoundset()
iterate over all records of the foundset, that should copied to a new one
get the dataProviders with something like rec.dataprovider()
get the value of each dataprovider on a record rec.value()
be sure that the uuid dataprovider isnt copy to the new Record
set the values to a the new record over the dataproviders
persist the changes
Full code example would be:
var vMobileController = plugins.iBizClientWebService.mobileController();
var vFoundset = vMobileController.currentFoundset();
var vDatabaseManager = vMobileController.dataManager();
var copyFoundSet = vDatabaseManager.retrieveOrCreateFoundset("<datasource>:<label>");
for (var index = 0; index < vFoundset.size(); index++) {
var rec = vFoundset.record(index);
var loc = copyFoundSet.newRecord();
var newRecord = copyFoundSet.record(loc);
var allDataproviders = rec.dataprovider();
for(var i=0;i<allDataproviders.length;i++)
{
var dataProvider = allDataproviders[i];
var dataValue = rec.value(dataProvider);
if(dataProvider != "attribute_id")
{
newRecord.setValue(dataProvider, dataValue);
}
}
}
copyFoundSet.saveData();

Categories

Resources