Good day. I need to popluate a table from an external API and mostof the info I can get from 1 request however I need a second request to populate the developer column. However my promise function does not populate the table for some reason. Please tell me if I am doing something wrong.
The string devList is supposed to be put into the innerHTML of document.getElementById(curDev).
const req1=new XMLHttpRequest();
const rawgAPIkey="*******************"; //real key used here
const baseurl="https://api.rawg.io/api";
const url=new URL(baseurl+"/games");
var tbl=document.getElementById("gametable");
url.searchParams.set("key", rawgAPIkey);
req1.open("GET", url);
req1.responseType="text";
req1.send();
req1.onreadystatechange=function(){
if(req1.readyState===4 && req1.status===200){
var gameArr = JSON.parse(req1.responseText).results;
console.log(JSON.parse(req1.responseText).results);
for (let index = 0; index < gameArr.length; index++) {
var game;
let genres="";
let tempGenre=gameArr[index].genres;
for (let index4 = 0; index4 < tempGenre.length; index4++) {
genres += tempGenre[index4].name;
if(index4!=tempGenre.length-1){
genres+= ", ";
}
}
let platforms="";
let tempPlatforms=gameArr[index].platforms;
for (let index2 = 0; index2 < tempPlatforms.length; index2++) {
platforms += tempPlatforms[index2].platform.name;
if(index2!=tempPlatforms.length-1){
platforms+=", ";
}
}
let Tags="";
let tempTags=gameArr[index].tags;
for (let index3 = 0; index3 < 3; index3++) {
Tags += tempTags[index3].name;
if(index3!=2){
Tags+=", ";
}
}
let agerating="";
if(gameArr[index].esrb_rating!=null){
agerating=gameArr[index].esrb_rating.name;
}else{
agerating="Rating unavailiable";
}
tbl.innerHTML+=
"<tr>"
+" <td> " + " <p> " + gameArr[index].name + " </p> "
+ "<img class=\"gamepic\" src=\" "+ gameArr[index].background_image + " \" alt=\"CS:GO\">" + " </td> "
+ "<td id=\"developerID" + index + "\">" + "</td>"
+ "<td>" + gameArr[index].released + "</td>"
+ "<td>" + genres + "</td>"
+ "<td>" + agerating + "</td>"
+ "<td>" + platforms + "</td>"
+ "<td>" + Tags + "</td>";
let curDev="developerID"+index;
var url2=new URL(baseurl+"/games/"+gameArr[index].id);
url2.searchParams.set("key", rawgAPIkey);
var developer="";
async function getDev(){
let myProm= new Promise (function(success, fail){
const req2= new XMLHttpRequest();
req2.open("GET", url2);
req2.responseType="text";
req2.onload=function(){
if(req2.status===200){
var gamedevs=JSON.parse(req2.responseText).developers;
devList="";
for (let i = 0; i < gamedevs.length; i++) {
devList += gamedevs[i].name + " ";
}
success(devList);
}else{
fail("Developer unavailable");
}
};
req2.send();
});
document.getElementById(curDev).innerHTML= await myProm;
}
getDev();
}
}
}
EDIT 2:
Got it working by doing the following where I just populated the table in the same function where I set devList thus I am not using promises anymore:
async function popdevs(){
let req2= new XMLHttpRequest();
req2.open("GET", url2);
req2.responseType="text";
req2.onload=function(){
if(req2.status===200){
var gamedevs=JSON.parse(req2.responseText).developers;
devList="";
for (let i = 0; i < gamedevs.length; i++) {
devList += gamedevs[i].name + " ";
}
document.getElementById(curDev).innerHTML= devList;
//console.log(devList);
//success(devList);
return devList;
}else{
//console.log("Hello");
return "developer unavailable";
}
};
req2.send();
}
popdevs();
Related
I'm running a script and want to output an alert when it is finished loading all data.
The problem is, I have a for loop and call a MVC controller function,
but the alert is outputted/triggered bevor the data is loaded completely.
It seems like the data fetching from the controller runs asynchronously.
I added the async and await but it changed nothing.
Script:
async function checkform() {
$("#faRueckmeldungen").html("")
let _clipboard="";
var _fanr = $('#FaNr').val();
var _faArray = _fanr.replace(/\n/g, " ").split(" ");
for (var i = 0; i <= _faArray.length; i++) {
var _fA = _faArray[i];
if (_fA < 2013810000) {
(document.getElementById("FaNr")).style.backgroundColor = "OrangeRed";
alert("FaNr #" + _fA + " nicht korrekt!");
}
else {
var url = "/FaInfos/FaRueckmeldung";
$.get(url, { faNr: _fA }, await function (data) {
$("#faRueckmeldungen").append(data[0]);
_clipboard += data[1];
navigator.clipboard.writeText(_clipboard);
})
}
}
alert("finished")
}
Controller function:
public JsonResult FaRueckmeldung(string faNr)
{
if (faNr == null)
return null;
//Loading data from SAP
var faHead = SapInterClient.GetFaHead(faNr.ToString());
var faPos = SapInterClient.GetFaPos(faNr.ToString());
//<td>"++"</td>
string clippoard = "Fertigungsauftrag\tMaterialnummer\tAuftragsmenge\tStart Termin Soll\tStart Termin Ist\tEndtermin Soll\tEndtermin Ist\tPersonal Soll [min]\tPersonal Ist [min]";
string sret = "<table class=" + (char)34 + "table1" + (char)34 + #"><thead><tr>
<th>Fertigungsauftrag</th>
<th>Materialnummer</th>
<th>Auftragsmenge</th>
<th>Start Termin Soll</th>
<th>Start Termin Ist</th>
<th>Endtermin Soll</th>
<th>Endtermin Ist</th>
<th>Personal Soll [h]</th>
<th>Personal Ist [h]</th>";
decimal VgPers = 0;
decimal RuPers = 0;
for (int i = 0; i < faPos.RückgemeldeteLeistungRP.Count(); i++)
{
VgPers += faPos.RückgemeldeteLeistungTP[i];//VorgabePersonal
RuPers += faPos.RückgemeldeteLeistungRP[i];//FeedbackPersonal
}
string cellColor = "LightGreen";
if (VgPers/60 < RuPers)
cellColor = "Salmon";
foreach (var item in faPos.Vorgangsnummer)
{
clippoard += "\t VG " + item;
sret += "<th> VG " + item + "</th>";
}
clippoard += "\r\n";
sret += "</tr></thead>";
sret += "<tr><td>" + faNr + "</td><td>" + faHead.MatNr + "</td><td>" + faHead.GesamteAuftragsmenge + "</td><td>" + faHead.TerminierterStart.ToString("dd.MM.yyyy") + "</td><td>" + faHead.IstStartTermin.ToString("dd.MM.yyyy") + "</td><td>" + faHead.TerminiertesEnde.ToString("dd.MM.yyyy") + "</td><td>" + faHead.IstEndTermin.ToString("dd.MM.yyyy") + "</td><td>" + String.Format("{0:0.00}", VgPers / 60) + "</td><td bgcolor=" + (char)34 + cellColor + (char)34 + ">" + String.Format("{0:0.00}", RuPers) + "</td>";
clippoard += faNr + "\t" + faHead.MatNr + "\t" + faHead.GesamteAuftragsmenge + "\t" + faHead.TerminierterStart.ToString("dd.MM.yyyy") + "\t" + faHead.IstStartTermin.ToString("dd.MM.yyyy") + "\t" + faHead.TerminiertesEnde.ToString("dd.MM.yyyy") + "\t" + faHead.IstEndTermin.ToString("dd.MM.yyyy") + "\t" + String.Format("{0:0.00}", VgPers / 60) + "\t" + String.Format("{0:0.00}", RuPers);
for (int i = 0; i < faPos.GutmengeGesamt.Count(); i++)
{
clippoard += "\t" + faPos.GutmengeGesamt[i];
sret += "<td>" + faPos.GutmengeGesamt[i] + "</td>";
}
clippoard += "\r\n";
sret += "</tr></table>";
return Json(new List<string>{sret,clippoard}, JsonRequestBehavior.AllowGet);
}
Please help.
Best regards Simon
You forgot to add await before the $.get(url....). The await before function has no reason to be there. Add async if you make asynchronous calls in there, though I do not see any.
The idea is that you add await to the specific instruction that works asynchronously ( and you want to wait for it). In your case, your callback function that you send to get is not the async function, rather the .get() itself is the guy you're looking for. The callback function you send there is being executed after the api call is done, and it's handled by .get() itself.
So your code will look a little something like this:
await $.get(
url,
{ faNr: _fA },
function (data) {
$("#faRueckmeldungen").append(data[0]);
_clipboard += data[1];
navigator.clipboard.writeText(_clipboard);
}
)
The data is like this, basically:
Activity Deadline Responsible Status
Activity1 09/20/2020 some#gmail.com In progress
Activity2 10/10/2020 someother#gmail.com Finished
The code below loops through Responsible column to create a unique set of emails and then it loops through the data range to create a table containing the activities pending different than Cancelled and Finished, which will then be sent to each of the email in the am set of email to remember them which activities are waiting for their input/update.
Despite the piece where I compare the first responsible with the one from the second loop, the activities composing the tables are not separated correcltly.
One recipient gets his activities, but the other gets all of the activities and the email is sent twice to the latter.
Here is the log output for both loops/columns compared:
If you could shed a light here, that would be greatly appreciated:
function emailPendingActivity() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Atividades");
var startRow = 9; // First row of data to process
var numRows = sheet.getLastRow(); // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 24);
var data = dataRange.getValues();
//This creates the history table headers
var historyMsg = "<html>"
+ "<h2 style='color:darkred;font-size:22px;font-weight:bold;'>Atividades Pendentes</h2>"
+ "<body>"
+ "<table style=\"text-align:center\">"
+ "<tr style='color:darkred;font-size:12px;'>"
+ "<th>N°</th>"
+ "<th>Solicitante</th>"
+ "<th>Projeto</th>"
+ "<th>Natureza</th>"
+ "<th>Área</th>"
+ "<th>Atividade</th>"
+ "<th>Status</th>"
+ "<th>Prazo</th>"
+ "<th>Dias de Atraso</th>";
//This gets unique responsible people from Atividades sheet
var responsibles = [];
for (var j = 0; j < data.length; ++j) {
var rowResp = data[j];
responsibles.push(rowResp[7]);
}
var unique = (value,index,self) => {
return self.indexOf(value) === index
}
var uniqueResp = responsibles.filter(unique);
for (var n = 0; n < uniqueResp.length;++n) {
if (uniqueResp[n] != ''){
var respRow = uniqueResp[n];
for (var i = 0; i < data.length; ++i) {
var rowData = data[i];
var activityNo = rowData[0];
var resp = rowData[7];
var status = rowData[11];
//if ((status.indexOf('Concluído') == -1) || (status.indexOf('Cancelado') == -1)) {
if (activityNo != '') {
if (status != 'Concluído') {
if (status != 'Cancelado') {
if (resp === respRow){
Logger.log('resp: ' + resp);
Logger.log('respRow: ' + respRow);
Logger.log(status)
var solicitante = rowData[2];
var nature = rowData[3];
var project = rowData[4];
var area = rowData[5];
var activity = rowData[6];
var deadline = rowData[9];
var statusDays = rowData[13];
//var deadlineAsDate = Utilities.formatDate(deadline, SpreadsheetApp.getActive().getSpreadsheetTimeZone(), "dd/MM/yyyy");
historyMsg += "<tbody>"
+ "<tr>"
+ "<td>" + activityNo + "</td>"
+ "<td>" + solicitante + "</td>"
+ "<td style=\"text-align:center\">" + nature + "</td>"
+ "<td style=\"text-align:center\">" + project + "</td>"
+ "<td style=\"text-align:center\">" + area + "</td>"
+ "<td style=\"text-align:left\">" + activity + "</td>"
+ "<td style=\"text-align:center\">" + status + "</td>"
+ "<td style=\"text-align:center\">" + deadline + "</td>"
+ "<td style=\"text-align:center\">" + statusDays + "</td>"
+ "</tr>";
}
}
}
}
}
var message = "<HTML><BODY>"
+ historyMsg;
+ "</HTML></BODY>"
var subject = "Some subject";
MailApp.sendEmail({
name: "Specific Name",
to: respRow,
subject: subject,
htmlBody: message
});
}
}
}
Solution
You are instantiating the historyMsg variable outside the for-loop. Basically you will append every row to this previously instantiated HTML table. You can't continue to append the values if you want to send only the corresponding one to the correct email address.
You should instantiate a new historyMsg for each uniqueResp element. So that the table will be build accordingly to your if conditions.
Proposed modification
function emailPendingActivity() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Atividades");
var startRow = 9; // First row of data to process
var numRows = sheet.getLastRow(); // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 24);
var data = dataRange.getValues();
//Move this into the for loop so it will create a unique message for each recipient
/**var historyMsg = "<html>"
+ "<h2 style='color:darkred;font-size:22px;font-weight:bold;'>Atividades Pendentes</h2>"
+ "<body>"
+ "<table style=\"text-align:center\">"
+ "<tr style='color:darkred;font-size:12px;'>"
+ "<th>N°</th>"
+ "<th>Solicitante</th>"
+ "<th>Projeto</th>"
+ "<th>Natureza</th>"
+ "<th>Área</th>"
+ "<th>Atividade</th>"
+ "<th>Status</th>"
+ "<th>Prazo</th>"
+ "<th>Dias de Atraso</th>";*/
//This gets unique responsible people from Atividades sheet
var responsibles = [];
for (var j = 0; j < data.length; ++j) {
var rowResp = data[j];
responsibles.push(rowResp[7]);
}
var unique = (value,index,self) => {
return self.indexOf(value) === index
}
var uniqueResp = responsibles.filter(unique);
for (var n = 0; n < uniqueResp.length;++n) {
if (uniqueResp[n] != ''){
var respRow = uniqueResp[n];
//This creates the history table headers
var historyMsg = "<html>"
+ "<h2 style='color:darkred;font-size:22px;font-weight:bold;'>Atividades Pendentes</h2>"
+ "<body>"
+ "<table style=\"text-align:center\">"
+ "<tr style='color:darkred;font-size:12px;'>"
+ "<th>N°</th>"
+ "<th>Solicitante</th>"
+ "<th>Projeto</th>"
+ "<th>Natureza</th>"
+ "<th>Área</th>"
+ "<th>Atividade</th>"
+ "<th>Status</th>"
+ "<th>Prazo</th>"
+ "<th>Dias de Atraso</th>";
for (var i = 0; i < data.length; ++i) {
...
I want to create a dynamic table in jQuery. But my code creates a table for each of my element.
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
var str = dataItem.Description;
var spl = str.split(','), part;
var spl2 = "";
for (var i = 0; i < spl.length; i++) {
part = spl[i].split(':');
content = "<table>" + "<tr><td>" + part[0] + "</td>" + "<td>" + part[1] + "</td></tr>";
spl2 += content;
}
content += "</table>"
var desc = "<div id='openModal' class='modalDialog'>" + "<span>" +
spl2
+ "</span><br/>" +
+ "</div>";
Which part of my code is wrong?
as you were adding table in for loop, so it was creating table for each item.Try this:
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
var str = dataItem.Description;
var spl = str.split(','), part;
var spl2 = "";
content ="<table>"
for (var i = 0; i < spl.length; i++) {
part = spl[i].split(':');
content += "<tr><td>" + part[0] + "</td>" + "<td>" + part[1] + "</td></tr>";
spl2 = content;
}
content += "</table>"
// you can also assign spl2 = content; over here.
var desc = "<div id='openModal' class='modalDialog'>" + "<span>" +
spl2
+ "</span><br/>" +
+ "</div>";
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
var str = dataItem.Description;
var spl = str.split(','), part;
var spl2 = "";
var content = "<table>";
for (var i = 0; i < spl.length; i++) {
part = spl[i].split(':');
content += "<tr><td>" + part[0] + "</td>" + "<td>" + part[1] + "</td></tr>";
spl2 += content;
}
content += "</table>"
var desc = "<div id='openModal' class='modalDialog'>" + "<span>" +
spl2
+ "</span><br/>" +
+ "</div>";
Updated your script
I have this code:
for(var i = 0; i < localStorage.length; i++){
var dataNya = JSON.parse(localStorage.key(i));
// console.log(dataNya);
var displayUlit = "";
displayUlit += "<br/>";
var spaceTo = "";
spaceTo += " || ";
console.log(dataNya);
var keme = localStorage.getItem(localStorage.key(i));
$("#pangDisplay").append(dataNya + spaceTo + "<button class='pangEdit' value="+dataNya+">"+JSON.parse(keme)+"</button>" + " " + displayUlit);
console.log(JSON.parse(keme));
// localStorage.setItem(JSON.stringify(dataNya), JSON.stringify("complete"));
}
$(".pangEdit").click(function(e){
e.preventDefault();
var pangInput = $(".pangEdit").val();
console.log(pangInput);
localStorage.setItem(JSON.stringify(pangInput), JSON.stringify("complete"));
});
i want to get the key of the localstorage where i can pass the data and update its value. help me thanks
You can use an attached data attributes in jQuery for this:
for (var i = 0; i < localStorage.length; i++) {
var dataNya = localStorage.key(i);
var displayUlit = "";
displayUlit += "<br/>";
var spaceTo = "";
spaceTo += " || ";
var keme = localStorage.getItem(dataNya);
var button = "<button class='pangEdit' data-storagekey='" + dataNya + "' value='" + dataNya + "'>" + keme + "</button>";
$("#pangDisplay").append(dataNya + spaceTo + button + " " + displayUlit);
}
$(".pangEdit").click(function(e) {
e.preventDefault();
var dataNya = $(this).data('storagekey');
localStorage.setItem(dataNya, "complete");
});
This is a rather simple question, I am having problems inserting data from Javascript into an HTML table.
Here is an excerpt of my JavaScript:
UPDATED - I got rid of the two loops and simplified it into one, however there is still a problem..
for (index = 0; index < enteredStrings.length; index++) {
output.innerHTML += "<td>" + enteredStrings[index] + "</td>"
+ "<td>" + enteredStringsTwo[index] + "</td>";
nameCounter++;
total.innerHTML = "Total: " + nameCounter;
}
And here is an except of my HTML page:
<table id="nameTable">
<tr>
<th>First</th><th>Last</th>
</tr>
Updated Picture:
Try this (edited):
var tableContent = '<tr>';
for (index = 0; index < enteredStrings.length; index++) {
tableContent += "<td>" + enteredStrings[index] + "</td>";
nameCounter++; // I don't know if this should be there,
// logically the counter should be incremented here as well?
total.innerHTML = "Total: " + nameCounter;
}
tableContent += '</tr><tr>';
for (index = 0; index < enteredStringsTwo.length; index++) {
tableContent += "<td>" + enteredStringsTwo[index] + "</td>";
nameCounter++;
total.innerHTML = "Total: " + nameCounter;
}
tableContent += '</tr>';
output.innerHTML += tableContent;
Edit2 (for updated question code):
var tableContent = '<tr>';
for (index = 0; index < enteredStrings.length; index++) {
tableContent += "<td>" + enteredStrings[index] + "</td>"
+ "<td>" + enteredStringsTwo[index] + "</td>";
nameCounter++;
total.innerHTML = "Total: " + nameCounter;
}
tableContent += '</tr>';
output.innerHTML += tableContent;
Edit3 (after looking at the code sent in email):
var tableContent = "";
for (index = 0; index < enteredStrings.length; index++) {
tableContent += "<tr><td>" + enteredStrings[index] + "</td>"
+ "<td>" + enteredStringsTwo[index] + "</td></tr>";
nameCounter++;
total.innerHTML = "Total: " + nameCounter;
}
output.innerHTML = tableContent;
instead of closing the td you are opening new ones
try
for (index = 0; index < enteredStrings.length; index++) {
output.innerHTML += "<td>" + enteredStrings[index] + "</td>";
total.innerHTML = "Total: " + nameCounter;
}
for (index = 0; index < enteredStringsTwo.length; index++) {
output.innerHTML += "<td>" + enteredStringsTwo[index] + "</td>";
nameCounter++;
total.innerHTML = "Total: " + nameCounter;
}
UPDATE:
you are appending the html to the table instead of the row.
in this case, the browser created a row for you automatically after the each td is appended.
With slight modifications in your code,
var outputTbl = document.getElementById('nameTable');
var output = document.createElement("tr");
outputTbl.appendChild(output);
for (index = 0; index < enteredStrings.length; index++) {
output.innerHTML += "<td>" + enteredStrings[index] + "</td>";
total.innerHTML = "Total: " + nameCounter;
}
for (index = 0; index < enteredStringsTwo.length; index++) {
output.innerHTML += "<td>" + enteredStringsTwo[index] + "</td>";
nameCounter++;
total.innerHTML = "Total: " + nameCounter;
}
If you need to add inner html code here.
<table id="nameTable" style="width:300px;">
<tr>
<th>First</th><th>Last</th>
</tr>
</table>
You can use Jnerator in this case.
If this is your data:
var data = [
{ first: 'Cole', last: 'Alan'},
{ first: 'Michael', last: 'Scott'}
]
You can add them to you table in next way:
for(var i=0; i<data.length; i++) {
var item = data[i];
var row = $j.tr({ child:[$j.td(item.first), $j.td(item.last)] });
nameTable.appendChild(row.dom());
}
nameTotal.innerHTML = 'Total: ' + data.length;
This is example.