MVC Java script loop async controller data - javascript

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);
}
)

Related

Problems with JavaScript Promises and an API

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();

Append is just printing the text and not printing the data from my api...Please solve only using vanilla JS

This is my html
<tbody id="rqstusers">
</tbody>
This is my script and when i run it its just pasting the lines
function getusersdata() {
const myHeaders = new Headers();
myHeaders.append('Content-Type', 'application/json');
const url = "XXXXXXXXXXXXXXXXXX";
fetch(url)
.then(function (response) {
console.log(response.status);
return response.json();
})
.then(function (data) {
for (var i = 0; i < data.length; i++) {
var mydata = "<tr><td>" + data[i].name + "</td><td>" + data[i].email + "</td><td>" + data[i].mobilenumber + "</td><td>"
+ data[i].state + "</td><td>" + data[i].city + "</td><td>" + data[i].pincode + "</td></tr>";
rqstusers.append(mydata);
}
})
This is my output
UPDATED: Updated my code to
.then(function (data) {
var elem = document.getElementById("rqstusers");
for (var i = 0; i < data.length; i++) {
var mydata = "<tr><td>" + data[i].name + "</td><td>" + data[i].email + "</td><td>" + data[i].mobilenumber + "</td><td>"
+ data[i].state + "</td><td>" + data[i].city + "</td><td>" + data[i].pincode + "</td></tr>";
elem.innerHTML= elem.innerHTML + mydata;
}
This is my Output and due to that first row its considering my table as empty and search ,print , csv functions were not working now

Fill table in javascript with data from db

I have an html <table> that I need to fill with data from a database query. The query returns 10 rows and then sends the data to the method fill(data) to fill the table:
function getTopQ() {
alert("Get top Qs");
callServer('fill', 'checkConnection', false, 'SelectTopQues.php');
}
function fill(data) {
alert("ready to fill now");
$('#table').html('');
var search = '#table';
for (var i = 0; i < data.length; i++) {
$('#table').listview("refresh");
var Questions = data[i];
var str = '<td " ID="' + Questions[0] +
'" Question="' + Questions[1] +
'" UserID="' + Questions[2] +
'"CategoryId"' + '" SubCategoryId"' + '" DatePosted"' + '"';
str += '">'; //end li
str += '<a href="" data-transition="fade">';
str += Questions[1];
str += '</a>';
//str += '<span class="hiddenData">' + item[13] + '</span>';
str += '</td>';
$('#table').append(str);
$('#table').listview("refresh");
}
console.log(data);
console.log($('#table'));
$('#table').listview("refresh");
}

How can create toggleable divs using javascript's innerhtml function?

I am trying to import information from an XML file, and create a name which, when clicked, will show more information. This information will be inside a div with no display until the header has been clicked.
This is the idea. Doesn't work.
$(document).ready(function () {
$.ajax({
type: "Get",
dataType: "xml",
url: 'service.xml',
success: function (xml) {
$(xml).find('Service[Name="j1979"]').find("Define").each(function () {
var PID = $(this).attr("PID");
var name = $(this).find("Name").text();
var source = $(this).find("source").text();
var doffset = $(this).find("DOffset").text();
var type = $(this).find("Type").text();
var length = $(this).find("Lenght").text();
var scale = $(this).find("Scale").text();
var noffset = $(this).find("NOffset").text();
var units = $(this).find("Units").text();
var moreinfo = "<div id='moreinfo'>source += '\r\n' += doffset += '\r\n' += type += '\r\n' += length += '\r\n' += scale += '\r\n' += noffset += '\r\n' += units</div>";
document.getElementById("j1979").innerHTML += PID += " ";
document.getElementById("j1979").innerHTML += < p onclick = "document.getElementById('moreinfo').style.display = 'inline-block'" > += "\r\n";
document.getElementById("j1979").innerHTML += moreinfo;
});
}
});
});
Sorry for any obvious mistakes and/or ugly code.
I assume that this is what you want to achieve: DEMO
just assume that the script in the demo is inside the success function
first, you have some error in here
document.getElementById("j1979").innerHTML += < p onclick = "document.getElementById('moreinfo').style.display = 'inline-block'" > += "\r\n";
this will not add the p element to the element with id j1979 because you write it like that, where you should be writing it like this
document.getElementById("j1979").innerHTML += "<p onclick=\"document.getElementById('moreinfo').style.display = 'inline-block';\" ></p>";
note the quotes at start and end, and the closing tag
second, there's no word or anything inside the p element that indicates that you could click it to show more information, so put the PID inside the p like this
document.getElementById("j1979").innerHTML += "<p onclick=\"document.getElementById('moreinfo').style.display = 'inline-block';\">" + PID + "</p>";
here's the full code with some CSS style to hide it before the user click on the PID
$(document).ready(function () {
var PID = "testPID";
var name = "Random Name";
var source = "Google";
var doffset = "1000";
var type = "A-9001";
var length = "50CM";
var scale = "100";
var noffset = "0";
var units = "Some Units";
var moreinfo = "<div id='moreinfo'>source: " + source + "</br>" + "doffset: " + doffset + "</br>" + "type: " + type + "</br>" + "length: " + length + "</br>" + "scale: " + scale + "</br>" + "noffset: " + noffset + "</br>" + "units: " + units + "</div>";
document.getElementById("j1979").innerHTML += "<p onclick=\"document.getElementById('moreinfo').style.display = 'inline-block';\">" + PID + "</p>";
document.getElementById("j1979").innerHTML += moreinfo;
});
#moreinfo {
display: none;
}
#j1979 {
color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<div id="j1979"></div>
From the code you have, you can use '+' operator to concatenate strings.
When you need to use single quote inside string defined with single quote, you can use backslash (\) as escape character before it.
Also, you need to hide the div with class "moreinfo" initially.
As for new line, if you want each attribute in new line in moreinfo class, it can be achieved by using HTML "pre" tag or "br" tag or some other way.
So code would be:
var moreinfo = "<pre id='moreinfo' style='display:none'> source = " + source + "\r\n doffset = " + doffset + "\r\n type = " + type + "\r\n length = " + length + "\r\n scale = " + scale + "\r\n noffset = " + noffset + "\r\n units = " + units +"</pre>";
document.getElementById("j1979").innerHTML += '<p onclick="document.getElementById(\'moreinfo\').style.display = \'inline-block\'">\r\n' + PID + "</p>";
document.getElementById("j1979").innerHTML += moreinfo;
or
var moreinfo = "<div id='moreinfo' style='display:none'> source = " + source + "<br> doffset = " + doffset + "<br> type = " + type + "<br> length = " + length + "<br> scale = " + scale + "<br> noffset = " + noffset + "<br> units = " + units +"</div>";
document.getElementById("j1979").innerHTML += '<p onclick="document.getElementById(\'moreinfo\').style.display = \'inline-block\'">\r\n' + PID + "</p>";
document.getElementById("j1979").innerHTML += moreinfo;
If you want to toggle display on click, you can use ternary operator to give condition in onclick function:
var moreinfo = "<div id='moreinfo' style='display:none'> source = " + source + "<br> doffset = " + doffset + "<br> type = " + type + "<br> length = " + length + "<br> scale = " + scale + "<br> noffset = " + noffset + "<br> units = " + units +"</div>";
document.getElementById("j1979").innerHTML += '<p onclick="document.getElementById(\'moreinfo\').style.display == \'inline-block\' ? document.getElementById(\'moreinfo\').style.display = \'none\' : document.getElementById(\'moreinfo\').style.display = \'inline-block\'">\r\n' + PID + "</p>";
document.getElementById("j1979").innerHTML += moreinfo;
I wrote a program where I needed to toggle a div with javascript. I found a solution with this code.
function toggle( selector ) {
var nodes = document.querySelectorAll( selector ),
node,
styleProperty = function(a, b) {
return window.getComputedStyle ? window.getComputedStyle(a).getPropertyValue(b) : a.currentStyle[b];
};
[].forEach.call(nodes, function( a, b ) {
node = a;
node.style.display = styleProperty(node, 'display') === 'block' ? 'none' : 'block';
});
You can then call the function with:
toggle('.idOrClass');
make sure you use single quotes around the class or id name
Hope this helps! :)

Unknown error when calling Array.length

first of all i need to say that i don't have much experience with JS. currently i'm trying to implement an web application with MVC framework. I'm in a work to develop an app that is also compatible with Internet explorer. in that case i'm using following JS method to populate a table which is working fine with all the browsers....
function populateTable(array) {
document.getElementById("instalationTable").style.display = "block";
var table = document.getElementById("ActivityDescription_installationID");
table.innerHTML = "";
elementsInTable = array;
var x = 0;
for (i = 0; i < (array.length * 2) ; i++) {
//alert(i);
if ((i % 2) == 0) {
//ID Row
var row = table.insertRow(i);
var cell_1 = row.insertCell(0);
cell_1.innerHTML = "<input type='text' disable='' class='form-control' value=" + array[x] + ">";
x = x + 1;
var cell_2 = row.insertCell(1);
cell_2.innerHTML = "<span class='btn btn-default' onclick='showEditRow(this)'><img src='../../Content/images/1414409386_48-24.png' /></span>";
var cell_3 = row.insertCell(2);
cell_3.innerHTML = "<span class='btn btn-default' onclick='removeRow(this)'>X</apan>";
}
else {
//Detail Row
var rowDetails = table.insertRow(i);
var cell = rowDetails.insertCell(0);
//cell.colspan = "3";
cell.innerHTML = "<table style='background-color:rgb(98, 98, 98);color:black;border- radius: 5px;' margin:2%; >" +
"<tr>" +
"<td><input type='checkbox' id='"+x+"_appServer'/> Application Server</span></td>" +
"<td>" +
"<select id='" + x + "_appServerVersion'>" +
"<option>Application version</option>" +
"</select>" +
"</td>" +
"</tr>" +
"<tr>" +
"<td colspan='2'><input type='radio' name='database' id='"+x+"_emptyDb' onChange='enableOptions(1)'/>" +
" Empty Database</br><input type='radio' name='database' id='" + x + "_instalationSlt' onChange='enableOptions(2)'/> Something Databse</td>" +
"</tr>" +
"<tr id='emptyDB'>" +
"<td>" +
"Oracle Version"+
"<select id='JS_OraVersion' name='" + x + "_oraVersion' style='width:100%'>" +
"<option>Ora version</option>" +
"</select>" +
"</td>" +
"<td>" +
"Character Set" +
"<select id='JS_ChaSet' name='" + x + "_ChaSet' style='width:100%'>" +
"<option>Cha Set</option>" +
"</select>" +
"</td>" +
"</tr>" +
"<tr id='dbImport'>" +
"<td>" +
"Something version" +
"<select id='JS_ImportVersion' name='" + x + "_ImportVersion' style='width:100%'>" +
"<option>Something version</option>" +
"</select>" +
"</td>" +
"<td>" +
"Something Charachter" +
"<select id='JS_ImportChaSet' name='" + x + "_ImportChaSet' style='width:100%'>" +
"<option>Something Cha</option>" +
"</select>" +
"</td>" +
"</tr>" +
"<tr>" +
"<td colspan='2'>" +
"Additional Requests </br>" +
"<textarea rows='4' id='" + x + "_specialReq' cols='37'> </textarea>" +
"<td/>"+
"</tr>"+
"</table>";
rowDetails.style.display = 'none';
Lock();
}
}
document.getElementById("instalationTable").style.display = "block";
}
i'm populating a form on the above table row, that collects some data to continue. to collect data i'm using following function which works fine with Google chrome but not with Internet explorer..
function getAllData() {
var StringtoSent = "";
for (i = 0; i < (elementsInTable.length) ; i++) {
var InsId = elementsInTable[i];
var _appServer = document.getElementById((i + 1) + "_appServer").checked;
var _appServerVersionDropDown = document.getElementById((i + 1) + "_appServerVersion");
var _appServerVersion = _appServerVersionDropDown.options[_appServerVersionDropDown.selectedIndex].value;
var _emptyDb = document.getElementById((i + 1) + "_emptyDb").checked;
var _instalationSlt = document.getElementById((i + 1) + "_instalationSlt").checked;
var _oraVersionDropDown = document.getElementsByName((i + 1) + "_oraVersion")[0];
var _oraVersion = _oraVersionDropDown.options[_oraVersionDropDown.selectedIndex].value;
var _ChaSetDropDown = document.getElementsByName((i + 1) + "_ChaSet")[0];
var _ChaSet = _ChaSetDropDown.options[_ChaSetDropDown.selectedIndex].value;
var _ImportVersionDropDown = document.getElementsByName((i + 1) + "_ImportVersion")[0];
var _ImportVersion = _ImportVersionDropDown.options[_ImportVersionDropDown.selectedIndex].value;
var _ImportChaSetDropDown = document.getElementsByName((i + 1) + "_ImportChaSet")[0];
var _ImportChaSet = _ImportChaSetDropDown.options[_ImportChaSetDropDown.selectedIndex].value;
var _specialReq = document.getElementById((i + 1) + "_specialReq").value;
StringtoSent = StringtoSent + "," + InsId + "," + _appServer + "," + _appServerVersion + "," + _emptyDb + "," + _instalationSlt + "," + _oraVersion + "," + _ChaSet + "," + _ImportVersion + "," + _ImportChaSet + "," + _specialReq + "|";
//return StringtoSent;
document.getElementById("ActivityDescription_instalationDetails").value = StringtoSent;
}
}
following image shows the error that im getting when it is ruining on VS 2012s IIS Express.
for (i = 0; i < (elementsInTable.length) ; i++) {
is the place that indicates as the error place . it always highlight the "elementsInTable.length" code segment.
Actually this error message elaborate nothing. i found some articles about the same error but occurring when trying to change the inner HTML of an element. but those solutions are not compatible for this situation.. Please help me with the problem
thanks in advance
Finally i found the Error
cell.innerHTML = "<table style='background-color:rgb(98, 98, 98);color:black;border- radius: 5px;' margin:2%; >" +
in above line i mistakenly added a CSS attribute "margin:2%;" in to a wrong place. Google chrome is intelligence enough to manage the situation and proceed the activity but Internet Explorer is not. as i found, this is the fact that prompt same error in different situations.
EG:
http://www.webdeveloper.com/forum/showthread.php?22946-innerHTML-amp-IE-Unknown-Runtime-Error
http://www.webdeveloper.com/forum/showthread.php?22946-innerHTML-amp-IE-Unknown-Runtime-Error
So if you got any unknown error in your Java Script code which uses "element.InnerHTML" or "document.Write" its better to check whether your tags are properly closed.
and i found several other situations that is generating same error
IE shows run time error for innerHTML
InnerHTML issue in IE8 and below
most of the times you can avoid this error by following W3C tag recommendations (http://www.w3.org/TR/html401/struct/global.html).

Categories

Resources