Reasons To Move Your Page's Cheese
If you want to avoid:
- jQuery's
Alert()
because it's "plain jane" and not very programmable - jQuery UI's dialog because of the overhead and hassle of using it
- directing the user to another page because you want to keep your design simple and the user on the same page (literally)
...a "poor man's SPA" design might interest you.
Here's how I did it, when I wanted the results of an AJAX call to display on the same page as the button that invoked the process, and then programmatically move down the page to display those results:
Add an Empty Container
At the place where you want the data to go, add a placeholder like so:
<div id="tableshell"></div>
In my case, I added that to the very end of the HTML (the bottom of the page); I add a dynamically created HTML table, that's why it's named "tableshell
".
Snatch and Plop the Data
Now all you need to do is get the data (the setting up of the Controller side of the AJAX call is left as an exercise for you, o wise and googlemeisterly reader, although the code of the method itself is shown below) via an AJAX call and assign it to that div
:
$("#btnViewList").click(function () {
$("#lblrptgenprogress").removeClass("invisible");
document.body.style.cursor = 'wait';
$.ajax({
type: "GET",
url: '@Url.Action("GenerateReportFutures", "GenerateScheduledRpts")',
success: function (retval) {
$("#tableshell").append($(retval));
document.getElementById("tableshell").scrollIntoView();
$("#lblrptgenprogress").addClass("invisible");
document.body.style.cursor = 'pointer';
},
error: function () {
alert('error in btnViewList');
}
});
});
As you can see, when a button (with the ID "btnViewList
") is clicked, I:
- Show an explanatory label (by removing the label's "invisible" class)
- Show an "hourglass" (by setting the cursor to 'wait')
- Make the AJAX call to get the data (the first arg passed to Url.Action() is the name of the method; the second arg is the controller name sans the "Controller" appendage)
- In the AJAX call's "success" function, append the returned data to the "placeholder" div
- Scroll the page so that the new data is at the top of the page (user has to scroll/page up to return to where they were before)
- Make the "progress" label invisible again by adding back the "invisible" class
- Remove the "hourglass" cursor by setting the cursor back to the default "pointer"
Dirt Banned
Now for the nitty gritty, here's the rest of the related HTML:
<div class="col-md-7">
<button class="btn pseudobtn darkgreentext marginaboveandbelow" id="btnViewList">
View List of Future Report Generation</button>
<label id="lblrptgenprogress" class="invisible redfont">
Report generation list is being constructed...</label>
</div>
...and CSS:
.invisible {
visibility: hidden;
}
.redfont {
color: red;
}
...and (last but not least) C# (Server side/Controller method called by jQuery AJAX):
public class GenerateScheduledRptsController : Controller
{
private static List<queuedreports> futureReports;
public string GenerateReportFutures()
{
StringBuilder sb = new StringBuilder();
futureReports = GetAllFutureReports();
try
{
sb.Append("<div class=\"row\">");
sb.Append("<div class=\"col-md-12\">");
sb.Append("<hr />");
sb.Append("</div>");
sb.Append("</div>");
sb.Append("<h2 class=\"titletext\" style=\"width: 50%;
margin: 0px auto;\">REPORTS TO BE GENERATED</h2>");
sb.Append("<br />");
sb.Append("<table class=\"centeredmargined\" border=\"1\" >");
sb.Append("<tr>");
sb.Append("<th nowrap>Report Name</th>");
sb.Append("<th nowrap>Unit</th>");
sb.Append("<th nowrap>Generation Date</th>");
sb.Append("<th nowrap>Data Begin Date</th>");
sb.Append("<th nowrap>Data End Date</th>");
sb.Append("<th>Recipients</th>");
sb.Append("</tr>");
foreach (QueuedReports qr in futureReports)
{
if (qr.NextExecution > DateTime.Now.AddMonths(3))
{
continue;
}
sb.Append("<tr>");
sb.Append(string.Format("<td nowrap>{0}</td>", qr.ReportName));
sb.Append(string.Format("<td nowrap>{0}</td>", qr.Unit));
sb.Append(string.Format("<td nowrap>{0}</td>", qr.NextExecution.ToLongDateString()));
sb.Append(string.Format("<td nowrap>{0}</td>",
qr.NextExecutionsBeginDateArg.ToLongDateString()));
sb.Append(string.Format("<td nowrap>{0}</td>",
qr.NextExecutionsEndDateArg.ToLongDateString()));
sb.Append(string.Format("<td>{0}</td>", qr.AllEmailAddresses));
sb.Append("</tr>");
}
sb.Append("</table>");
return sb.ToString();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return sb.ToString();
}
Knock Yourself Out/Go Wild
Of course, you don't have to append your dynamically generated HTML exclusively to the end of a page; you can put it after any element where it makes sense to do so, such as after a button when you want to show some message or feedback to the user relevant to their clicking the button, or...wherever you want.