how to read/use imported table from API into javascript? - javascript

I am using an API from Caspio to import a Data Table that will be variable.
for that, I am doing the following
<script type="text/javascript" id='Test' src="https://c1afw487.caspio.com/dp/6e444000877ca58e63624b0b8c78/emb"></script>
and then to format it (send it to the bottom of my web page) I am doing this:
<div id='InfoTable' style='width: 40%; float: left;'>
<a id='TestTwo' href="https://c1afw487.caspio.com/dp/6e444000877ca58e63624b0b8c78">DataTable </a>
</div>
Now, I am trying to access the data from the table. For that I am trying something like this
var DataTest = document.getElementById('Test');
var DataTestTwo = document.getElementById('TestTwo');
console.log(JSON.stringify(DataTest));
console.log(JSON.stringify(DataTestTwo));
But the first test returns { } and the second one null (notice how I tried to give an ID to the imported table so I could access it but any of my attempts worked).
What is the proper way to access the Table?

I dont know anything about that specific API but quick google seems to suggest that they have a separate rest api for requesting JSON data. You should look into that.
Stringifying an html element does nothing usefull...its an html element not your request payload data.
You can go over the table itself and extract all the contents into a json.
Something like this.
https://jsfiddle.net/rainerpl/wvdoek03/14/
var getHeaders = (table) => {
const headerRow = table.tBodies[0].children[0];
const headers = [];
let i;
for (i = 0; i < headerRow.children.length; i++) {
headers.push(headerRow.children[i].innerText);
}
return headers;
}
var getData = (table) => {
const data = [];
let i;
for (i = 1; i < table.tBodies[0].children.length; i++) {
let newDataRow = [];
for (j = 0; j < table.tBodies[0].children[i].children.length; j++) {
newDataRow.push(table.tBodies[0].children[i].children[j].innerText);
}
data.push(newDataRow);
}
return data;
}
JsonTable = function() {
const table = document.getElementsByTagName('table')[0];
const headers = getHeaders(table);
const data = getData(table);
this.getRow = (rowNr) => {
const result = {};
headers.forEach((key, index) => {
result[key] = data[rowNr][index];
});
return result;
}
console.log('table', table, 'has data:', data, ' and headers ', headers);
}
const jsonTable = new JsonTable();
console.log('First row is', jsonTable.getRow(0));
console.log('Second row is', jsonTable.getRow(1));
You can view the console output on jsFiddle to see what it looks like.
( use inspect developer tool to see console output )

Related

Not able to add list items to HTML Document

I am using fetch() command to get an array of data in JSON format. I am using function fetchURL() to get data in JSON format. I use async-await. Then in each data received I am trying to add it's login field to an ordered list that I have created in the HTML file.
I have made a createListItem() function to find the ordered list tag in the HTML file and append in it the login field. But first I try to store all the login fields in an array arr. But I am not able to store the login fields in it.
But when I directly use createListItem() function to create a list item with login" field as text I am able to add these fields to the ordered list and hence I get the ordered list.
I am commenting out the lines that get me direct Output on the browser window when I do not store the login fields in the arr:
Code:
function createListItem(text) {
const parent = document.getElementsByTagName("ol");
const entry = document.createElement("li");
entry.textContent = text;
parent[0].appendChild(entry);
}
const url = "https://api.github.com/users ";
async function fetchURL() {
return (await fetch(url)).json();
}
let arr = [];
async function createList() {
const data = await fetchURL();
for (let i = 0; i < data.length; i++) {
//createListItem(`${data[i].login}`);
arr.push(data[i].login);
}
}
createList();
you are getting the data in array, you need to create list after you call createList() function:
createList().then(function(){
arr.forEach(element => {
createListItem(element);
});
});
you can also define arr in the createList function and return that then your code would be like this:
async function createList() {
let arr = [];
const data = await fetchURL();
for (let i = 0; i < data.length; i++) {
//createListItem(`${data[i].login}`);
arr.push(data[i].login);
}
return arr;
}
createList().then(arr=>{
arr.forEach(element => {
createListItem(element);
});
});
You can achieve your objective with just one async function:
const url="http://jsonplaceholder.typicode.com/users";
async function getList(u){
const arr=(await fetch(u).then(r=>r.json())).map(e=>e.username);
document.querySelector("ol").innerHTML=arr.map(u=>`<li>${u}</li>`).join("");
console.log(arr);
}
getList(url);
<h2>List of login names</h2>
<ol></ol>
<p>end of page</p>
In the above snippet I used the public resource provided by typicode.com and extracted the property of username instead of login.

Codestructure in async javascript

I have a simple program that reads a css file (which is available on GitHub pages) and parse the css to an array so I can put at in a list.
I have an dictionary with words, like a vocabulary list which shows me the translation and I can also search for words.
Everything works fine so far but I am really new and this is my first project and I want some advise about my codestructure.
At the moment I have to fetch the csv file (which never changes) in different methods with getData. I do this in init dictionary and again in search and show, because I need the dictionary again. Wouldn’t it be better to get the data once and then use it with all functions?
But then I have to write a lot function into another which is not so good practice I think.
I would really appreciate some advise or link or topics/ direction I have to research, because I can’t find an answer about how to structure this well.
I just use html, css and js without any framework or library.
initDictionary();
async function initDictionary(){
//get data
const dictionary = await getData();
//fill html list with words
fillList(dictionary);
}
//show translation and info when click on word
show = async function (i){
let dictionary = await getData();
document.getElementById("word-text").innerHTML = dictionary[i].Wort;
document.getElementById("info").innerHTML = dictionary[i].Notizen;
}
//search stuff
search = async function() {
let dictionary = await getData();
let query = document.getElementById('search').value;
console.log(query);
if (query == ""){
return;
}
//init found to false
let found = -1;
for(let i=0; i< dictionary.length; i++){
if(query == dictionary[i].Übersetzung){
found = i;
break;
}else {
document.getElementById("word-text").innerHTML = "word not found";
document.getElementById("info").innerHTML ="";
}
}
if ( found >= 0){
show (found);
query = document.getElementById('search').value="";
}
}
//Start search when u press enter
let input = document.getElementById("search");
input.addEventListener("keyup", function(event) {
console.log(event);
if (event.key=== "Enter") {
search();
}
});
// get data
async function getData(){
const csv = await fetch('https://aboutwhite.github.io/data/data.csv');
let scvText = await csv.text();
let dictionary = csvToArray(scvText);
return dictionary;
}
// fill html list with words
function fillList(dictionary){
for(let i=0; i< dictionary.length; i++){
document.getElementById('word-list').innerHTML += "<li onclick='show("+i+")'>" + dictionary[i].Übersetzung+"</li>";
}
}
//parse csv to array
function csvToArray(str){
let delimiter = ","
const headers = str.slice(0, str.indexOf("\n")).split(delimiter);
const rows = str.slice(str.indexOf("\n") + 1).split("\n");
const arr = rows.map(function (row) {
const values = row.split(delimiter);
const el = headers.reduce(function (object, header, index) {
object[header] = values[index];
return object;
}, {});
return el;
});
return arr;
}

How to make react stop duplicating elements on click

The problem is that every time I click on an element with a state things appear twice. For example if i click on a button and the result of clicking would be to output something in the console, it would output 2 times. However in this case, whenever I click a function is executed twice.
The code:
const getfiles = async () => {
let a = await documentSpecifics;
for(let i = 0; i < a.length; i++) {
var wrt = document.querySelectorAll("#writeto");
var fd = document.querySelector('.filtered-docs');
var newResultEl = document.createElement('div');
var writeToEl = document.createElement('p');
newResultEl.classList.add("result");
writeToEl.id = "writeto";
newResultEl.appendChild(writeToEl);
fd.appendChild(newResultEl);
listOfNodes.push(writeToEl);
listOfContainers.push(newResultEl);
wrt[i].textContent = a[i].data.documentName;
}
}
The code here is supposed to create a new div element with a paragraph tag and getting data from firebase firestore, will write to the p tag the data. Now if there are for example 9 documents in firestore and i click a button then 9 more divs will be replicated. Now in total there are 18 divs and only 9 containing actual data while the rest are just blank. It continues to create 9 more divs every click.
I'm also aware of React.Strictmode doing this for some debugging but I made sure to take it out and still got the same results.
Firebase code:
//put data in firebase
createFileToDb = () => {
var docName = document.getElementById("title-custom").value; //get values
var specifiedWidth = document.getElementById("doc-width").value;
var specifiedHeight = document.getElementById("doc-height").value;
var colorType = document.getElementById("select-color").value;
parseInt(specifiedWidth); //transform strings to integers
parseInt(specifiedHeight);
firebase.firestore().collection("documents")
.doc(firebase.auth().currentUser.uid)
.collection("userDocs")
.add({
documentName: docName,
width: Number(specifiedWidth), //firebase-firestore method for converting the type of value in the firestore databse
height: Number(specifiedHeight),
docColorType: colorType,
creation: firebase.firestore.FieldValue.serverTimestamp() // it is possible that this is necessary in order to use "orderBy" when getting data
}).then(() => {
console.log("file in database");
}).catch(() => {
console.log("failed");
})
}
//get data
GetData = () => {
return firebase.firestore()
.collection("documents")
.doc(firebase.auth().currentUser.uid)
.collection("userDocs")
.orderBy("creation", "asc")
.get()
.then((doc) => {
let custom = doc.docs.map((document) => {
var data = document.data();
var id = document.id;
return { id, data }
})
return custom;
}).catch((err) => {console.error(err)});
}
waitForData = async () => {
let result = await this.GetData();
return result;
}
//in render
let documentSpecifics = this.waitForData().then((response) => response)
.then((u) => {
if(u.length > 0) {
for(let i = 0; i < u.length; i++) {
try {
//
} catch(error) {
console.log(error);
}
}
}
return u;
});
Edit: firebase auth is functioning fine so i dont think it has anything to do with the problem
Edit: This is all in a class component
Edit: Clicking a button calls the function createFileToDb
I think that i found the answer to my problem.
Basically, since this is a class component I took things out of the render and put some console.log statements to see what was happening. what i noticed is that it logs twice in render but not outside of it. So i took the functions out.
Here is the code that seems to fix my issue:
contain = () => {
const documentSpecifics = this.waitForData().then((response) => {
var wrt = document.getElementsByClassName('writeto');
for(let i = 0; i < response.length; i++) {
this.setNewFile();
wrt[i].textContent = response[i].data.documentName;
}
return response;
})
this.setState({
docs: documentSpecifics,
docDisplayType: !this.state.docDisplayType
})
}
As for creating elements i put them in a function so i coud reuse it:
setNewFile = () => {
const wrt = document.querySelector(".writeto");
const fd = document.querySelector("#filtered-docs");
var newResultEl = document.createElement('div');
newResultEl.classList.add("result");
var wrtEl = document.createElement('p');
wrtEl.classList.add("writeto");
fd.appendChild(newResultEl);
newResultEl.appendChild(wrtEl);
}
The firebase and firestore code remains the same.
the functions are called through elements in the return using onClick.

can't get data form array

I try to get data from the array but I get undefined
please check the image of my problem
I don't know what I'm missing
please help
I have an array called nameTable of string
when I console.log(this.nameTable) I got this : check the image please
enter image description here
and when I click to arrow I got this : check image please
enter image description here
the problem is the table has 5 element I want to show them so I make for loop to do that
for (let i = 0; i < 5; i++){
console.log(this.nameTable[i])
}
but us you can see in the image I got undefined
enter image description here
here the code :
employeeL:Array<Awinjard> = [];
inv_agentTab: Array<Inv_agent> = [];
drafbiesTab: Array<Drafbies> = [];
nameemployee: string = "";
inv_agentNombre: number = 0;
matriculeTable: Array<number> = [];
nameTable:Array<string> = [];
validatationTable: Array<number> = [];
ngOnInit() {
this.folder = this.activatedRoute.snapshot.paramMap.get('id');
this.awinjard.getAwinjardMatricule().subscribe(res => {
this.inv_agentTab = res as Array<Inv_agent>
this.inv_agentTab.forEach(element => {
this.matriculeTable[this.inv_agentNombre] = element.AGENT;
this.validatationTable[this.inv_agentNombre] = element.VLD;
this.inv_agentNombre++;
this.awinjard.getAwinjardNameAr().subscribe(res2 => {
this.drafbiesTab = res2 as Array<Drafbies>
this.drafbiesTab=this.drafbiesTab.filter((employee)=>employee.DECAFFE==element.AGENT)
this.nameemployee = this.drafbiesTab[0].AR_DELAFFE;
this.nameTable.push(this.nameemployee);
})
});
for (let i = 0; i < 5; i++){
// here the problem I can't get the data form nameTable array
console.log(this.nameTable[i])
let awin= <Awinjard> {
matricule: this.matriculeTable[i],
fullname: this.nameTable[i],
status: true,
done: 1,
mustBeDone:40
}
this.employeeL.push(awin);
}
})
}
You have subscribed to getAwinjardNameAr and before that response, you are trying to access the nameTable array, which is why you get undefined. #raishav-hanspal's solution is right to solve your issue, but a code change can keep things straightforward. I suggest you to write that code inside your for loop inside your subscribe. Here's the alteration:
this.awinjard.getAwinjardNameAr().subscribe(res2 => {
this.drafbiesTab = res2 as Array<Drafbies>
this.drafbiesTab=this.drafbiesTab.filter((employee)=>employee.DECAFFE==element.AGENT)
this.nameemployee = this.drafbiesTab[0].AR_DELAFFE;
this.nameTable.push(this.nameemployee);
let awin= <Awinjard> {
matricule: this.matriculeTable[this.inv_agentNombre],
fullname: this.nameemployee,
status: true,
done: 1,
mustBeDone:40
}
this.employeeL.push(awin);
})
You can move the code where you're logging nameTable[] inside the subscribe (where you are pushing the values into nameTable[]).
A complete solution is to use complete in subscribe() -->
this.awinjard.getAwinjardNameAr().subscribe(res2 => {
this.drafbiesTab = res2 as Array<Drafbies>
this.drafbiesTab=this.drafbiesTab.filter((employee)=>employee.DECAFFE==element.AGENT)
this.nameemployee = this.drafbiesTab[0].AR_DELAFFE;
this.nameTable.push(this.nameemployee);
},err => {console.log(err)}, ()=> {
for (let i = 0; i < 5; i++){
// here the problem I can't get the data form nameTable array
console.log(this.nameTable[i])}})
});
You can read more on https://angular.io/guide/observables

How to fetch and display a specific index in a JSON file using a Javascript loop

I am currently using fetch in javascript to obtain information from another site into my own. The issue I am having is, I am using a loop to display all of the indexes of the JSON file into my site. I actually want to get specific indexes to show, not all of them, for example, index 2,4 and 6.
Here is my code so far:
window.addEventListener("load", (event)=>{
const requestURL = 'https://byui-cit230.github.io/weather/data/towndata.json';
fetch(requestURL)
.then(function (response) {
return response.json();
})
.then(function (jsonObject) {
const towns = jsonObject['towns'];
for (let i = 0; i < towns.length; i++ ) {
let towninfo = document.createElement('section');
let townname = document.createElement('h2');
townname.textContent = towns[i].name;
towninfo.appendChild(townname);
document.querySelector('div.weathertowns').appendChild(towninfo);
}
});
})
This displays all of the towns in reference, but I only want to display the title of 3 specific ones. Any suggestions on how to proceed with this?
something like that
window.addEventListener("load", (event)=>
{
const requestURL = 'https://byui-cit230.github.io/weather/data/towndata.json'
, divWeathertowns = document.querySelector('div.weathertowns')
;
fetch(requestURL)
.then( response=>response.json() )
.then( jsonObject=>
{
const towns = jsonObject['towns']
;
for ( let i of [2,4,6] )
{
let towninfo = document.createElement('section')
, townname = document.createElement('h2')
;
townname.textContent = towns[i].name;
towninfo.appendChild(townname);
divWeathertowns.appendChild(towninfo);
}
});
})
<div class="weathertowns"></div>

Categories

Resources