Ajax POSTS not updating screen content - javascript

So I have a "scenario", made up of lots of "forms" which contain lots of "events" and "data" etc. To populate all this information I have this in the page to run once the page is finished
$(document).ready(function() {
var scenarioID = ${testScenarioInstance.id}
var myData = ${results as JSON}
populateFormData(myData, scenarioID);
});
This then calls the functions below (the first calls the second, done like this as I had an issue where as it was ajax the variables in the loop were updating before things were being appended and so everything ended up in the last sub table): -
function populateFormData(results, scenarioID) {
$table = $('#formList')
for ( var i in results) {
var formIDX = (results[i]["forms_idx"])
var formID = (results[i]["form_id"])
appendSubTable(formIDX, scenarioID, $table, formID);
}
}
function appendSubTable(formIDX, scenarioID, $table, formID) {
var url = "http://localhost:3278/FARTFramework/testScenario/ajaxPopulateSubTables"
$.post(url, {
formIDX : formIDX, scenarioID : scenarioID, formID :formID
}, function(data) {
var $subTable = $table.find("#" + formIDX).find('td:eq(1)').find("div").find("table")
$subTable.append(data)
}).fail(function() {
alert("it failed!")
});
}
This then goes off grabs the data from the controller like so..
def ajaxPopulateSubTables(int formIDX, int scenarioID, int formID) {
def db = new Sql(dataSource)
String mySQL = "Loads of SQL STUFF"
def subTableResults = db.rows(mySQL)
render(template: "subTableEntry", model: [subTableResults:subTableResults, formID:formID, formIDX:formIDX])
}
and fires it at the gsp:
<colgroup>
<col width="150"/>
<col width="350"/>
<col width="350"/>
<col width="350"/>
</colgroup>
<g:if test="${subTableResults != null && !subTableResults.isEmpty()}">
<tr>
<th>eventIDX</th>
<th>eventID </th>
<th>objID</th>
<th>testVal</th>
</tr>
</g:if>
<g:each in="${subTableResults}" status = "i" var="item">
<tr id = ${i} class="${((i) % 2) == 0 ? 'even' : 'odd'}" name="main">
<td>${item.events_idx}</td>
<td>${item.type}</td>
<td>${item.object_description}</td>
<td><g:textField id = "testData[${formIDX}:${formID}:${i}]" name="testData[${formIDX}:${formID}:${i}]" value="${item.value}" optionKey="id" /></td>
</tr>
</g:each>
Before then jamming it into the relevant sub table.
The problem is, sometime when I load up a page not all the sub tables are filled out, but if I hit F5 to refresh the page this then seems to fix the issue... Although not always, sometimes I then get a different section not refreshing :(
I put a println into the controller to see if all the SQLs were being fired off but it always returns all the individual form SQL strings fine...
Looking in firebug all the POSTs are coming back fine but the page just isn't updating...
Any suggestions or ideas as to what might be causing this would be appreciated, I'm at a loss..
I also tried updating my appendSubTable function where the post is to include a fail in case something was failing, but this isn't hit either, have updated code above to show this

Oddly I altered the post function slightly to the below, moving the finding of the table to the beginning of the function rather than within the post itself and that seems to have done the trick, although why I'm not sure... Whether someone can explain why this is or not I'd be interested to know why!
function appendSubTable(formIDX, scenarioID, $table, formID) {
var $subTable = $table.find("#" + formIDX).find('td:eq(1)').find("div").find("table")
var url = "http://localhost:3278/FARTFramework/testScenario/ajaxPopulateSubTables"
$.post(url, {
formIDX : formIDX, scenarioID : scenarioID, formID :formID
}, function(data) {
$subTable.append(data)
}).fail(function() {
alert("fail")
});
}

Related

req.body.Dates is not defined

I have 2 drop down menus that are dynamically being populated using SQL Server. Based on the selected items, I am loading a different ejs template. I have done this using the help of AJAX. However, I want to be able to load the data according to the selected criteria. For instance, if DD1 is selected as Andrew and DD2 as Date the table should load 7 columns based on those conditions.
AKA
SELECT * FROM exTable x WHERE x.Name = 'Andrew' and x.Date = '4/22/2019'
What I have already tried is to pass the selected item from the dropdown to the router, like so:
router.js
router.post('/selection', async (req, res) =>{
try {
var nameFromDB = await conn.query("SELECT DISTINCT pr.Name FROM WFS.Table1 pr WHERE pr.Group = 'Test'");
var dateFromDB = await conn.query('SELECT r.Date FROM WFS.Table2 r');
var tables = ("SELECT * FROM WFS.view v WHERE v.Date= '" + req.body.Dates + "' AND v.Name = '" + req.body.Names + "'");
console.log("SELECT * FROM WFS.view v WHERE v.Date= '" + req.body.Dates + "' AND v.Name = '" + req.body.Names + "'");
res.render('selection', {tables: tables, nameFromDB : nameFromDB , dateFromDB: datesFromDB});
}
catch (err) {
res.status(500)
res.send(err.message)
}
});
This is the output of the console.log :
SELECT top 100 * FROM WFS.view_workRequests_Extended v WHERE v.Revenue_Release_Id = '04/16/2019' AND v.Development_Manager = 'Andrew'
app.js
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use('/', router);
index.ejs
<script>
$(document).ready(function() {
$('#DDD').on('change', function(event) {
var selectedDate = $('#selections option:selected').val();
});
$('#DDN').on('change', function(event) {
var selectedName = $('#selection option:selected').val();
});
$('#submitData').on('submit', function(e){
e.preventDefault();
$.ajax({
type: "POST",
url: "/selection",
data: {selectedDate : selectedDate, selectedName : selectedName },
success: function() {
alert('success');
}
});
});
});
</script>
<form action="/selection" method="POST">
<select class="DateDD" id="DDD" name="Dates">
<% for(var n=0; n < dateFromDB.recordset.length; n++) { %>
<option><%= dateFromDB.recordset[n].Date%></option>
<% } %>
</select>
<select class="NameDD" id="DDN" name="Names">
<% for(var n=0; n < nameFromDB.recordset.length; n++) { %>
<option><%= nameFromDB.recordset[n].Name%></option>
<% } %>
</select>
<input type="submit" name="Submit" id="submitData" class="btn btn-primary" value="View Report" />
</form>
selection.ejs
CONTAINS THE SAME THING AS INDEX.EJS (besides the script tag) AND ...
<table class="table table-bordered table-condensed table-striped">
<% for(var n=0; n < tables.recordset.length; n++) { %>
<tr>
<td><%=tables.recordset[n].Name%></td>
<td><%=tables.recordset[n].Date%></td>
....
....
</tr>
<% } %>
</table>
After form submit on index.ejs this error gets thrown:
Dates is not defined
I don't know whats causing this error, because I am able to see the name and date in the console being printed. Any help would be appreciated, thank you!
You've intercepted onsubmit event and modified the names of the data sent through ajax
$.ajax({
type: "POST",
url: "/selection",
data: {selectedDate : selectedDate, selectedName : selectedName }, // <-- here
success: function() {
alert('success');
}
});
So you're reading the wrong property in your req.body. You should instead read like:
// for date
req.body.selectedDate
// for name
req.body.selectedName
Also you claim
I am able to see the name and date in the console
The output of console you've put doesn't match the query in the code in question.
This is basic debugging question.
I can advice you to do couple of things like:
Check the browser devTools (network tab) to see if the body payload is being passed to the server.
On the server (express), are you using body parser middleware ? see more here (req.body section).
Try to run nodejs with inspect mode and attach your IDE (VSCode is a good one) and add some breakpoints. Alternatively, you can do some console.logs in order to check what are you getting from the client.
You can simulate a browser request using postman to check the server side and make sure it is working fine.
This is a simple error, so no big deal, frustrating as I know it can be.
I see you using dates, date, Date & Dates. I would look for a line number reference to give me a clue. I would use chrome and developer tools or console.log to see how far I get.
Or, I would use a different name convention like date1, date2, date3, date4 or something that is even more descriptive, so I knew for sure which date was what, then on narrowing down the error, it will be much easier to fix.

How do I populate a list field in a model from javascript?

I have a Kendo.MVC project. The view has a model with a field of type List<>. I want to populate the List from a Javascript function. I've tried several ways, but can't get it working. Can someone explain what I'm doing wrong?
So here is my model:
public class Dashboard
{
public List<Note> ListNotes { get; set; }
}
I use the ListNotes on the view like this:
foreach (Note note in Model.ListNotes)
{
#Html.Raw(note.NoteText)
}
This works if I populate Model.ListNotes in the controller when the view starts...
public ActionResult DashBoard(string xsr, string vst)
{
var notes = rep.GetNotesByCompanyID(user.ResID, 7, 7);
List<Koorsen.Models.Note> listNotes = new List<Koorsen.Models.Note>();
Dashboard employee = new Dashboard
{
ResID = intUser,
Type = intType,
FirstName = user.FirstName,
LastName = user.LastName,
ListNotes = listNotes
};
return View(employee);
}
... but I need to populate ListNotes in a Javascript after a user action.
Here is my javascript to make an ajax call to populate ListNotes:
function getReminders(e)
{
var userID = '#ViewBag.CurrUser';
$.ajax({
url: "/api/WoApi/GetReminders/" + userID,
dataType: "json",
type: "GET",
success: function (notes)
{
// Need to assign notes to Model.ListNotes here
}
});
}
Here's the method it calls with the ajax call. I've confirmed ListNotes does have the values I want; it is not empty.
public List<Koorsen.Models.Note> GetReminders(int id)
{
var notes = rep.GetNotesByCompanyID(id, 7, 7);
List<Koorsen.Models.Note> listNotes = new List<Koorsen.Models.Note>();
foreach (Koorsen.OpenAccess.Note note in notes)
{
Koorsen.Models.Note newNote = new Koorsen.Models.Note()
{
NoteID = note.NoteID,
CompanyID = note.CompanyID,
LocationID = note.LocationID,
NoteText = note.NoteText,
NoteType = note.NoteType,
InternalNote = note.InternalNote,
NoteDate = note.NoteDate,
Active = note.Active,
AddBy = note.AddBy,
AddDate = note.AddDate,
ModBy = note.ModBy,
ModDate = note.ModDate
};
listNotes.Add(newNote);
}
return listNotes;
}
If ListNotes was a string, I would have added a hidden field and populated it in Javascript. But that didn't work for ListNotes. I didn't get an error, but the text on the screen didn't change.
#Html.HiddenFor(x => x.ListNotes)
...
...
$("#ListNotes").val(notes);
I also tried
#Model.ListNotes = notes; // This threw an unterminated template literal error
document.getElementById('ListNotes').value = notes;
I've even tried refreshing the page after assigning the value:
window.location.reload();
and refreshing the panel bar the code is in
var panelBar = $("#IntroPanelBar").data("kendoPanelBar");
panelBar.reload();
Can someone explain how to get this to work?
I don't know if this will cloud the issue, but the reason I need to populate the model in javascript with an ajax call is because Model.ListNotes is being used in a Kendo Panel Bar control and I don't want Model.ListNotes to have a value until the user expands the panel bar.
Here's the code for the panel bar:
#{
#(Html.Kendo().PanelBar().Name("IntroPanelBar")
.Items(items =>
{
items
.Add()
.Text("View Important Notes and Messages")
.Expanded(false)
.Content(
#<text>
#RenderReminders()
</text>
);
}
)
.Events(e => e
.Expand("getReminders")
)
)
}
Here's the helper than renders the contents:
#helper RenderReminders()
{
if (Model.ListNotes.Count <= 0)
{
#Html.Raw("No Current Messages");
}
else
{
foreach (Note note in Model.ListNotes)
{
#Html.Raw(note.NoteText)
<br />
}
}
}
The panel bar and the helpers work fine if I populate Model.ListNotes in the controller and pass Model to the view. I just can't get it to populate in the javascript after the user expands the panel bar.
Perhaps this will do it for you. I will provide a small working example I believe you can easily extend to meet your needs. I would recommend writing the html by hand instead of using the helper methods such as #html.raw since #html.raw is just a tool to generate html in the end anyways. You can write html manually accomplish what the helper methods do anyway and I think it will be easier for you in this situation. If you write the html correctly it should bind to the model correctly (which means it won't be empty on your post request model) So if you modify that html using javascript correctly, it will bind to your model correctly as well.
Take a look at some of these examples to get a better idea of what I am talking about:
http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
So to answer your question...
You could build a hidden container to hold your list values like this (make sure this container is inside the form):
<div id="ListValues" style="display:none">
</div>
Then put the results your ajax post into a javascript variable (not shown).
Then in javascript do something like this:
$('form').off('submit'); //i do this to prevent duplicate bindings depending on how this page may be rendered futuristically as a safety precaution.
$('form').on('submit', function (e) { //on submit, modify the form data to include the information you want inside of your ListNotes
var data = getAjaxResults(); //data represents your ajax results. You can acquire and format that how you'd like I will use the following as an example format for how you could save the results as JSON data: [{NoteID ="1",CompanyID ="2"}]
let listLength = data.length;
for (let i = 0; i < listLength; i++) {
$('#ListValues').append('<input type="text" name="ListNotes['+i+'].NoteID " value="' + data.NoteID +'" />')
$('#ListValues').append('<input type="text" name="ListNotes['+i+'].CompanyID " value="' + data.CompanyID +'" />')
//for your ajax results, do this for each field on the note object
}
})
That should do it! After you submit your form, it should automatically model bind to you ListNotes! You will be able to inpsect this in your debugger on your post controller action.

Tried to load table dynamically using AJAX but rows not displayed

In a form, i have a dropdownlist and a textbox which will get user's input. Then when the user submits the form, i don't want the whole page to refresh. i only wanted the table which is just below it to refresh and load data from database. I tried code below but only alert pops up. The table is still empty.
$('#frmPrescDrugList').submit(function (e) {
e.preventDefault(); // Prevent Default Submission
$.ajax({
url: '/consultation/PrescDrugList',
type: 'POST',
data: $(this).serialize(), // it will serialize the form data
dataType: 'html',
success: function (data) {
var row_data = "";
row_data += "#{ var rowNum = 0; } #foreach (var item in Model.LoadDrugList) {
rowNum += 1;
<tr Class="odd gradeX">
<td>#rowNum</td>
<td>#item.dsubsystem</td>
<td>#item.tradename </td>
<td style="text-align: center; vertical-align: middle;"><form Class="form-horizontal" role="form" action="#Url.Action("Prescription", "consultation", new {dgid = item.dgid})" method="post"><Button type="submit" Class="btn btn-default" name="btnDrugListSelect">Select</Button></form></td>
</tr>
}";
$("#LoadDrugListTable").append(row_data);
alert('Drug list has been loaded.');
},
error: function () {
alert('Ajax Submit Failed ...');
}
}); // end ajax
}); // end form-submit
LoadDrugListTable is the table's id. Why didn't it load the data when the ajax is already successful? Can anyone please help point out my mistake or suggest me a better example reference?
I tried following this example, but i'm stuck at the #Url.Action(). Its underlined red. And when i try to separate them by "" and + it's still underlined red saying
Too many characters in character literal.
UPDATED
This is the form i mentioned that doesn't pass the id properly. I'm passing it to a get method. By the way, this is an entirely different page than the one i mentioned above. When i try to do the same thing in another page, it passes a null paid value. Paid is the id. Maybe because this time i'm passing to another page.
"<td style='text-align: center; vertical-align: middle;'><form Class='form-horizontal' role='form' action='#Url.Action("PatientMedicalInfo", "consultation", new { paid = Html.Raw(" + data[i].paid + ") }) method='get'><Button Class='btn btn-default' name='btnSelectPatient' id='btnSelectPatient'>Select</Button></form></td>"
This is the controller:
[HttpGet()]
public ActionResult PatientMedicalInfo(string paid)
{
PatientLookupVM Patient = new PatientLookupVM();
dynamic CurrentPatientDetailsByPtId = Patient.GetCurrentPatientDetailsByPtId(paid);
Patient.LoadCurrentPatientDetails = CurrentPatientDetailsByPtId;
return View(Patient);
}
Try replacing double " quotes with single ' quotes in action.
Well for consistency you could replace them everywhere.
<td ... action='#Url.Action("Prescription", "consultation", new {dgid = item.dgid})' ... </td>

Regarding Population of Grid data with Ajax Polling

I have a Map which contains the status information as a value for a object.The Ajax should poll the map and update the status on the grid.I am facing issue in updating the same.
The code snippet I am using is:
setInterval(
$.post("./listStatus.action", {
method: "getStatus",
}, function( data, success ) {
if ( success == "success" ) {
var rowsIds = statusGrid.getDataIDs();
console.log("Row Ids:"+rowsIds);
for(var i=0;i<data.statusList.length;i++){
var rowData=statusGrid.jqGrid('getRowData',data.statusList[i].rowID);
rowData["Status"] =data.statusList[i].Status;
statusGrid.jqGrid('setRowData', data.statusList[i].rowID, rowData);
}
}
}),5000);
On first call its able to show the data however in second call onwards it gives Uncaught SyntaxError: Unexpected identifier
Can anybody help me out how to implement the use case and how to resolve the issue as i am new to JS.
Thanks
I don't know if this answers your question exactly but, it might get you going. In my experience with jqGrid my automatic grid refreshes looked something like this.
If my HTML looked like this:
<div style="margin: 10px;">
<table id="custGrid"></table>
<div id="ptoolbar"></div>
<div id="pager" class="scroll" style="text-align: center;"></div>
</div>
The the javascript has this:
var grid = $("#custGrid");
jQuery("#custGrid").jqGrid({ ... });
when I refresh the data in the grid I would do something like this:
jQuery("#custGrid").jqGrid('setGridParam', { search: true, postData: { filters: postobj }, page: 1 });
jQuery("#custGrid").trigger("reloadGrid");
The trigger reload tells jqGrid to fetch new data based on the revised grid parameters.
Hope this helps.
setInterval takes a function as first parameter :
setInterval(function () {
$.post("./listStatus.action", {
method: "getStatus",
}, function (data, success) {
if (success == "success") {
var rowsIds = statusGrid.getDataIDs();
console.log("Row Ids:" + rowsIds);
for (var i = 0; i < data.statusList.length; i++) {
var rowData = statusGrid.jqGrid('getRowData', data.statusList[i].rowID);
rowData["Status"] = data.statusList[i].Status;
statusGrid.jqGrid('setRowData', data.statusList[i].rowID, rowData);
}
}
});
}, 5000);
I haven't checked the rest of your code.

How do I create a web link inside a javascript function and pass cell value as a parameter to servlet?

I am creating a table dynamically with JavaScript as you can see below. I want users to be able to click on the first column value and pass the value of the cell as a parameter to a J#EE servlet. Can you help me? Basically the first column should be links to a new page with a country details. How can I do that? Thank you.
Where do I put the link code?
function oneSecondFunction() {
$.get('DisplayCountries', function(responseJson) {
if (responseJson != null) {
$("#countrytable").find("tr:gt(0)").remove();
var table1 = $("#countrytable");
$.each(responseJson, function(key, value) {
var rowNew = $("<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td>" +
"<td></td><td></td></tr>");
rowNew.children().eq(0).text(value['id']);
rowNew.children().eq(1).text(value['country1']);
rowNew.children().eq(2).text(value['country2']);
rowNew.children().eq(3).text(value['country3']);
rowNew.children().eq(4).text(value['country4']);
rowNew.children().eq(5).text(value['country5']);
rowNew.children().eq(6).text(value['country6']);
rowNew.children().eq(7).text(value['country7']);
rowNew.children().eq(8).text(value['country8']);
rowNew.appendTo(table1);
});
}
});
and here is the link code. I have tried several options and it doesn't work.
id
First, assign a class to the first <td> something like <td class="linkHolder">.
Then, write a click handler to send ajax request to servlet:
$('#countrytable').on('click', '.linkHolder', function() {
var link = $(this).html();
$.post('/myservlet', {url: link}, function(response) {
//handle response here
});
return false;
});
You can access the link on the servlet side with the request parameter url

Categories