I have a element on my page that looks like this
<td><span class="badge badge-danger">Stopped</span></td>
and I want to update it based on things that are going on in the code.
Take this example.. I have a button and that element, and when I click that button I want to start downloading a list of names. Once it's started I want the text inside that span to say "Started" rather than "Stopped" and than once the code finished running aka the list of names has been downloaded, I want it to say "Done" rather than "Started"
And I've been reading back and forth about how to do this and it seems as if I need to implement ajax somehow and I'm not sure how to.
I guess the button would invoke a asp-action="StartDownload" and then it would look something like this..
public ActionResult StartDownload()
{
StartDownload();
return View("WhereSpanIs");
}
private void StartDownload()
{
//Set span text to "Started" some how
//Finished download
//Set span text to "Done" some how
}
For manipulating HTML in the browser when requested by a controller method as in your approach, you would need something like SignalR to enable communication between the server (i.e. controller) and client (i.e. browser).
As you already found out, it's easier using Ajax to update the text in this case (using JavaScript/JQuery). Like in the following example, you could set the text when the button has been clicked, and when the request is complete:
In the view:
<script type="text/javascript">
// call this method on button click
function startDownload() {
// loading, TODO: update the text)
$.ajax({
type: "GET",
url: '#Url.Action("StartDownload", "Home")',
contentType: "application/json; charset=utf-8",
success: function(data) {/* done, TODO: update the text */ },
error: function() { /* error, TODO: update the text }
});
}
</script>
In the (Home) controller:
public ActionResult StartDownload()
{
// TODO: perform the download
return Json(new {status = "OK"});
}
JSON is used to allow the result to be interpretable in JavaScript, although it is not used in this example.
See the Shopping Cart Tutorial for further information.
Related
How can I show a loading Gif animation by using a jquery in asp.net project in Main.Master page? Whenever its taking time, I would like to show this Gif.
I searched on internet but they are showing this loading images for one control only. Thats why i need to keep this jquery at one place (ie: in master page) and want too use it on all content page whenever its taking too much time to load the page (either first time the page loads or button clicked or any event taking time)
$.ajax({
type: "POST",
url: "~/Jobs/ExportJobEntry.aspx",
data: dataString,
beforeSend: loadStart,
complete: loadStop,
success: function() {
$('#form').html("<div id='msg'></div>");
$('#msg').html("Thank you for your email. I will respond within 24 hours. Please reload the page to send another email.")
},
error: function() {
$('#form').html("<div id='msg'></div>");
$('#msg').html("Please accept my apologies. I've been unable to send your email. Reload the page to try again.")
}
return False);
});
$(document).ready(function () {
$(document).ajaxStart(function () {
$("#loading").show();
}).ajaxStop(function () {
$("#loading").hide();
});
});
I used this code but it is not working
You can use jQuery BlockUI plugin. Here is official website, please read documentation
http://malsup.com/jquery/block/
You can do it like this
$(document)
.ajaxStart(function () {
$loading.show();
})
.ajaxStop(function () {
$loading.hide();
});
Then you can define $loading how ever you want
I'm playing with JQuery, and I'm trying to fire a Click event on a button, to run off to a handler in my asp.net application, and getting some strange results.
I'll post the code and then explain whats happening :-
$(function () {
$("[id$='btnClaimValidate']").click(callSwapClaimHandler);
function callSwapClaimHandler() {
$.ajax({
type: 'POST',
url: "/handlers/investor-tickets/claimswapvalidator.ashx",
data: {
investorId: $("[id$='hdnInvestor']").val(),
investorTicketId: $("[id$='hdnInvestorTicket']").val(),
originalClaimId: $("[id$='hdnInvestorTicketClaimId']").val(),
newClaimId: $("[id$='txtClaim']").val()
},
dataType: "html",
error: function () {
alert("failure");
},
success:
function (data) {
var $newdiv = data;
$("[id$='divMessageData']").append($newdiv);
}
});
}
});
With the code above, the handler is never called. The event is 100% being fired on click. I've tested by removing the ajax post function, and replaced it with a simple alert("Hello); command to be sure.
What is strange is that if i register the click event to actually execute on DOM load by doing this :-
$("[id$='btnClaimValidate']").click(callSwapClaimHandler());
The handler is fired as the page loads and then works as expected.
By taking off the parenthesis, so that it is only fired on click, the post never actually executes.
I've debugged the browser session, and the function runs, but it never gets to the handler, and no content is returned.
Can anyone explain what's going wrong?
Your comment to #Scarface Ron is the clue. Your page is refreshing as the default button behavior was not stopped. Also just use the function inline in the handler:
$(function () {
$("[id$='btnClaimValidate']").click(function (e) {
// Stop the button actioning!
e.preventDefault();
$.ajax({
type: 'POST',
url: "/handlers/investor-tickets/claimswapvalidator.ashx",
data: {
investorId: $("[id$='hdnInvestor']").val(),
investorTicketId: $("[id$='hdnInvestorTicket']").val(),
originalClaimId: $("[id$='hdnInvestorTicketClaimId']").val(),
newClaimId: $("[id$='txtClaim']").val()
},
dataType: "html",
error: function () {
alert("failure");
},
success:
function (data) {
var $newdiv = data;
$("[id$='divMessageData']").append($newdiv);
}
});
});
});
apologies if I got the closing braces wrong here
The simple explanation here is that your button selector - [id$='btnClaimValidate'] - isn't matching anything at the time it is executed. Hard to say why (you're generating that part of the DOM after the page is loaded? You have a typo?) but you can test this easily enough:
$(function()
{
alert($("[id$='btnClaimValidate']").length);
});
If the value is 0, then this is your problem and you'll have a specific area to investigate further.
Alternately, use your browser's DOM inspector to verify that an event has actually been attached to the button after the load has completed.
If the problem is simply that the button is added to the DOM after the page is loaded, then you might want to consider using a delegated event instead of attaching the handler directly to the button. For instance:
$("document").on("click", "[id$='btnClaimValidate']", callSwapClaimHandler);
This will attach the event to the document (which exists) but mandate that the handler is only called when the event has bubbled up from the button (which may not exist yet when the handler is bound, but probably will later).
Is there any chance, when I select a row from asp:dropdownlist, dynamically change page, execute sql query and after result, change selected row in second asp:dropdownlist?
If this isn't possible only with asp.net and codebehind, please let me know how to execute SELECT-query in javascript (may be with Ajax; but I don't understand it) and change second dropdown's selected row.
Thanks!
Its a bit of a generic question because there is a couple of options that you could do plus I'm not 100% sure what you want to do. In short you could use AJAX to contact a PHP page which will do an operation on your database. A result it generated and sent back to the client. You could use JSON to hold the data that is getting sent to the browser.
All AJAX does is allow you to get data from another location based on the URI you give. I would use the JQuery library as it makes it easy to implement AJAX.
// This will trigger ajax whenever the is a change in the drop down. I am assuming the drop down class is .dropdown
$('.dropdown').change(function() {
$.ajax({
type: "POST",
url: "page_change.php",
data: { name: "about_us" }
dataType:JSON,
success: function(data) {
//The data returned from test.php is loaded in the .result tag
$('.result').html(data.html);
// If you want to change page you would execute
window.location(data.url);
}
});
});
page_change.php will then contact your database and generate JSON.
More information about JQuery AJAX here:
http://api.jquery.com/jQuery.ajax/
You will need to look at JQuery, AJAX, PHP and JSON to change data on your page.
If you just want to change page on a drop down change I suppose you could store the page name in the option id?
$('.dropdown').change(function() {
var page = $(this).attr('id');
window.location(page + ".html");
});
I have few jquery tabs on a usercontrol that loads a separate user control under each. Each user control is unique. It all works fine right now but the overall page response is too slow. In order to improve performance I am trying to load few user controls under these tabs on demand (that is on click of tab). Possibly without post back... ajaxish.
Can anyone guide me?
I tried to follow this tutorial and this one too but did not have any success. I have attached the code for parent usercontrol.
<ul id="tabs">
<li class="active">Rewards</li>
<li id="liCoupons">Coupons</li>
<li id="liLibrary">Library</li>
<li id="liProducts">Favorite</li>
<li id="liPreferences">Preferences</li></ul><ul id="tabPanes" class="rewardsTabs">
<li>
<div class="wrapper active">
<uc:Rewards ID="wellness" runat="server" />
</div>
</li>
<li id="liCoupons">
<div class="wrapper">
<uc:Coupon runat="server" />
</div>
</li><li id="liLibrary">
<div class="wrapper">
<uc:Library runat="server" />
</div>
</li><li id="liProducts">
<div class="wrapper">
<uc:Products runat="server" />
</div>
</li>
<li>
<div class="wrapper">
<div class="preferences">
<uc:Preferences runat="server"/>
</div>
</div>
</li>
The second link you mentioned should work. You don't need to define any user controls in your markup.
<ul id="tabs">
<li class="active">Rewards</li>
<li id="liCoupons">Coupons</li>
<li id="liLibrary">Library</li>
<li id="liProducts">Favorite</li>
<li id="liPreferences">Preferences</li>
</ul>
<div id="results" class="wrapper"></div>
Each tab click will do an ajax call
$.ajax({
type: "POST",
url: "Default.aspx/WebMetodToCall",
data: data, // I wouldn't prefer passing webmethod name here
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
$('#result').html(msg.d);
},
failure: function (msg)
//error
}
});
to the web methods.
[WebMethod]
public static string Rewards()
{
return RenderControl("~/controls/rewardsControl.ascx");
}
[WebMethod]
public static string Coupons()
{
return RenderControl("~/controls/couponsControl.ascx");
}
...
Each method will render only the requested control. Also in your method you can keep or extract the viewstate depending on your needs. After rendering, the webmethod should pass back the html string to be injected into the placeholders.
If you tried this and were successful rendering one control at a time but still seeing slowness then you have some back end issues while getting the data. If your controls are data heavy I would recommend doing some server side caching.
Hope this helps.
Does your user controls rely on post-backs and view-state for there working? It will be relative easy to fetch the user control HTML to be displayed in the tab using AJAX but then post-back on that control will send the entire data to the actual page (that may not have the user control loaded). So the basic outline would be
Track the active tab using hidden variable or view-state.
Load the user control based on active tab in the early page cycle. The best bet would be init stage (not that view-state won't be available here, so you have to store active tab in hidden variable and access it via Request.Forms collection).
Give each user control a ID and it should be different from tab to tab. ID is very important for loading the view-state.
If you get corrupted view-state errors at tab switching then you need to first load the user control for the previous tab and then at later page stage (say load/prerender), unload it and load new user control for active tab.
You can use a placeholder or panel control within each tab pane to load the user control in the correct location.
Needless to say, on change of jquery tab, you need to submit your form using post-back script. After every post-back, you need to have a script to re-initialize tabs and selecting active tab.
For better user experience, put entire thing into an UpdatePanel.
perhaps use an anchor that points to the service defined below. For instance,
<li></li>
/// <summary>
/// Service used by ajax for loading social media content
/// </summary>
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ControlService
{
/// <summary>
/// Streams html content
/// </summary>
/// <param name="type">type of control</param>
/// <returns>html stream of content</returns>
[OperationContract]
[WebGet(UriTemplate = "Content?cType={cType}")]
public Stream GetContent(string cType)
{
var tw = new StringWriter();
var writer = new Html32TextWriter(tw);
var page = new Page();
var control = page.LoadControl(cType);
control.RenderControl(writer);
writer.Close();
var stream = new MemoryStream(Encoding.UTF8.GetBytes(tw.ToString()));
WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
WebOperationContext.Current.OutgoingResponse.Headers.Add("Cache-Control", "no-cache");
return stream;
}
}
You will need to make an Ajax call in order to make this.
now you have options to call AJAX:
1 - Call via SOAP web service (ASP AjaxScriptManager referencing will be needed for every web method).
2- Call via WCF Service as the previous answer.
3 - Call via Rest service.
4- Call via Jquery ajax method but the request must going to external page like "Actions.aspx" so when you call your method an HTTPRequest will be made into Actions page then it will have the returned data within its response. $.Ajax(url,data,action,successMethod); // this is the fastest way I tried them all.
Here is what you should to do:
1- on the change tab event call your method by using the appropriate Ajax calling method from the above options.
2- from the success method use the returned data but it's better for you to use eval(data) for the DataTime objects.
here is some example explains how to make this call:
var helper = {
callAjax: function(sentData, successFun) {
jQuery.ajax({
url: "/Actions.aspx",
type: "Get",
data: sentData,
cache: true,
dataType: "json",
success: successFun
});
}
};
helper.callAjax('request=getCities&countryID=' + countryID, function (args) {
var result = eval(args); // this object will contain the returned data
var htmlData = '';
for (var i=0;i<result.length;i++){
// write your HTML code by jQuery like this
htmlData += '<div>' + result[i].title + '</div>';
}
$('#tab3').html(htmlData);
});
now at the Actions.ASPX code use the following:
protected void Page_Load(object sender, EventArgs e)
{
object _return = new
{
error = "",
status = true
};
JavaScriptSerializer _serializer = new JavaScriptSerializer();
if (!Page.IsPostBack)
{
string str = Request.QueryString["request"].ToString();
switch (str.ToLower())
{
case "getcities":
int countryID = Convert.ToInt32(Request.QueryString["countryID"].ToString());
_return = JQueryJson.Core.City.getAllCitiesByCountry(countryID).Select(_city => new
{
id = _city.ID,
title = _city.Name
});
_serializer = new JavaScriptSerializer();
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "text/json";
Response.Write(_serializer.Serialize(_return));
break;
}
// etc........
}
If you adjust it a little with jquery, this should work:
http://blogs.msdn.com/b/sburke/archive/2007/06/13/how-to-make-tab-control-panels-load-on-demand.aspx
Or you just use the asp.net tabs.
You should go for the second link using jquery and webmethod. That way you will actually populate the tabs on demand without making you page heavy.
In my opinion, the fastest solution to your problem (but not necessarily the best long-term) is to wrap all your UserControls in a .aspx page. In this situation, you'd just have to move your parent UserControl markup to a new .aspx page, and call it via AJAX.
Assuming that you called this page something like Menu.aspx, and further assuming that you don't need any data passed into this page (that is, it can track all of its own data internally), your jQuery AJAX call would look something like this:
function GetMenu ($placeholder) {
$.ajax({ type: "POST", contentType: "application/json; charset=utf-8", dataType: "json",
url: "Menu.aspx",
done: function (result) {
$placeholder.html(result.d);
},
fail: function () {
$placeholder.html("Error loading menu.");
}
});
}
Some notes:
done and fail will replace success and error in jQuery 1.8, so any jQuery AJAX you use should plan for this transition.
I wrapped this in a function largely because I prefer to put AJAX calls inside JS classes and functions, and then reference those objects. With a menu, it's unlikely you'd have several different pages loading the same data via AJAX (since this will be on some sort of master page, I'm guessing), but it's always good to get yourself in the habit of doing these things.
Depending on your feelings about tightly-coupled HTML/JavaScript, you could replace $placeholder above with a callback function. Calling that from your the page where your menu resides would look something like:
$(document).ready(function () {
GetMenu(MenuCallback);
});
function MenuCallback(menuHtml) {
$("#menu").html(menuHtml); // I'm assuming the ID of your ul/span/div tag here.
}
Some people (myself included) use the $ prefix to differentiate between JavaScript and jQuery variables. So here, $placeholder is a jQuery variable.
You might be able to re-write this $.ajax call as a type: "GET", which would be a little bit more efficient, but I'm not sure if the UserControls would cause problems in that regard. Normally, if I'm loading an entire .aspx page via AJAX, I use GET instead of POST. You don't have to change much to try it out: just switch out the type property and change result.d to result.
I think the best solution is to implement client call back
http://msdn.microsoft.com/en-us/library/ms178210.aspx
When user clicks on some tab,onclick event calls js func with name of tab as parameter, than that tab calls server code with same parameter.
Than in code you load controls you want depending which tab is clicked.
Now you need to render controls into html and send tham back to js function.
Now you have controls in js function, find where you want to insert code an insert it.
that should work in theory and it is not to complicated :))
an asnwer (not mine) to this question is probably useful to you:
Asynchronous loading of user controls in a page
it states that there are problems with this with needing a form on the user control to post back, but that should be ok to have independent forms with ajax post. you'll have to think about what happens when posting the form(s) on the page, but shouldn't be insurmountable. shouldn't be any reason you couldn't just make it the ashx handler you have mentioned.
Here's the situation (using MVC 2.0):
I'm trying to build a feature to allow a user to preview changes they make to their bio/profile without actually committing their changes first. User fills out a form, clicks a "Preview" button and see what their changes look like. One difficulty is the front-end has a different master-page, so we need to render the whole view, not just a control.
Here's the approach I took:
Asynch post the serialized form to a controller action
Manipulate the model to flesh out the collections, etc. that don't get posted
Return the front-end view, passing it this modified model
Catch the response to the asynch method, wrap it in an iframe and write that to a lightboxed div on the page
Code I'm using... Controller action (the BuildPreview method just alters the model slightly)
[HttpPost]
[Authorize]
public ActionResult PreviewProfile(PersonModel model)
{
return View("Person", PeopleService.BuildPreview(model));;
}
HTML/Jquery stuff:
<script type="text/javascript">
$(document).ready(function () {
$("#previewButton").click(function (e) {
$.post("/PreviewProfile", $("#bioForm").serialize(), function (response) {
$("#previewFrame").html(response);
$("#holdMyPreview").modal({
overlayClose: true,
escClose: true,
autoResize: true,
}, "html");
});
});
});
The modal method is just a basic lightbox-esque thing.
Running into two problems:
EDIT - removed this, I was accidentally pulling a child control
The iframe isn't rendering the html (perhaps because it's not valid b/c it's missing html/body/head tags?). If I just drop the response direcltly into the div, without the iframe, it works... albiet with the wrong stylesheet. If I try to insert it into iframe it just treats it as an empty page, just the html, head and body tags show up.
Any thoughts?
Sam
PS: Tried this over at MSDN forums (http://forums.asp.net/t/1675995.aspx/1?Rendering+a+view+into+a+string+) and it didn't get anywhere, figured I'd see if SO has any brilliance.
so, just massage the response when you get it back, add the missing html/body/head
$.post("/PreviewProfile", $("#bioForm").serialize(), function (response) {
response = "<html><body>"+response+"</body></html>";
$("#previewFrame").html(response);
$("#holdMyPreview").modal({
overlayClose: true,
escClose: true,
autoResize: true,
}, "html");
});