I am using an updatepanel and I'd like to use the Sys.WebForms.PageRequestManager endRequest event to display a success message. But I can only get this event to fire when I generate an error in my procedure. My understanding is that it should fire all the time. What am I missing?
So, you don't give much context here.
but, lets use a update panel, drop in a simple button.
On button click, we will display a please wait.....
For code behind on button click, we just do a "sleep" for 4 seconds to fake a long running process.
When done, of course the post-back will automatic hide the please wait message, and then we have some javascript code run by using "end request".
so, first up, our markup in the UP, and a simple please wait....
(we don't need a UP for that simple please wait processing message, but lets just use a UP for this).
So, this:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<h3>Start the Big Process</h3>
<asp:Button ID="cmdStart" runat="server"
Text="Start Process" CssClass="btn"
ClientIDMode="Static"
OnClick="cmdStart_Click" />
<asp:UpdateProgress ID="UpdateProgress1" runat="server">
<ProgressTemplate>
<img src="Content/wait2.gif" width="64" />
Update in progress...
</ProgressTemplate>
</asp:UpdateProgress>
</ContentTemplate>
</asp:UpdatePanel>
So, how the "Progress Template works", is that area and markup is displayed DURING the post back. So, very handy.
So, say the code behind is this:
protected void cmdStart_Click(object sender, EventArgs e)
{
// fake 4 seconds long running
System.Threading.Thread.Sleep(4000);
}
So, when we run, we get/see this effect:
Now, of course we want a message, or at the very least to run some client side code AFTER the post-back (processing) is done.
Well, we can adop, use the very "long time" approach of simple using a register client script at the end of the code. And as such, no update panel event is required.
So, say after done, we want a client side alert(), or even better, say a toast message (any kind of client side js code is the goal here).
So, we could say do this:
protected void cmdStart_Click(object sender, EventArgs e)
{
// fake 4 seconds long running
System.Threading.Thread.Sleep(4000);
MyToast(this.Page, cmdStart.ClientID, "Processing Complete",
#"All steps for project<br/>are now complete", "6000");
}
void MyToast(Page mypage, string ctrlBeside,
string Heading, string strMessage,
string strDelay = "3000")
{
string strScript =
#"toastcall('#ctrlBeside','#Heading','#Text','#strDelay');";
strScript = strScript.Replace("#ctrlBeside", ctrlBeside);
strScript = strScript.Replace("#Heading", Heading);
strScript = strScript.Replace("#Text", strMessage);
strScript = strScript.Replace("#strDelay", strDelay);
ScriptManager.RegisterStartupScript(mypage, mypage.GetType(), "mytoast", strScript, true);
}
Now, I just have a toast message "helper" in above, and all it does is setup the js code, and inject (register). Do note that in place of Page.ClientScript.RegisterStartupScript, we used ScriptManger to register (we need to do this for update panels - other than that - same functionally).
And of course, I do assume in place of a simple alert(), that I have jQuery.toast installed.
So, I have this client side js code in that page:
function toastcall(sControl, sHeading, sMsg, sTime) {
var btn = $('#' + sControl)
var btnpos = btn.position()
$.toast({
heading: sHeading,
text: sMsg,
position: {top: (btnpos.top + btn.height()), left: btnpos.left + btn.width()},
icon: 'info',
hideAfter: sTime,
allowToastClose: false,
loader: false,
showHideTransition: 'slide'
});
}
And now we get this effect:
So far we really don't need that event, since the "last line" of the code behind is free like "any" and "all" code behind to inject some js script to run.
And if you want a another button on the page OUTSITE of UP to trigger that up?
Then just use a client side button, and use a "click" of a button inside of the UP.
Say like this:
<asp:Button ID="Button2" runat="server" Text="client side button - trigger update panel"
OnClientClick="$('#cmdStart').click();return false"
/>
So, the above will run the button inside of the UP, and not a full page post back.
However, just place that 2nd button in another UP, and that click will then ALWAYS load + post BOTH UP's. (in fact all on the given page will ALWAYS be posted back as a whole group of UP's). If you don't want all UP's posted back to the server, then you have to add this to the UP.
UpdateMode="Conditional"
So, keep in mind that multiple UP's all post back by default unless you add above. (of course that ONLY applies to a UP post-back, since with a regular button and post-back outside of UP, then you have a regular plain jane post-back).
So, do keep in mind that UP is in fact a post-back! - or better stated what we call a "partial page post back". And not that when using a UP, even the page load event fires EACH time.
So, a UP does not 100% eliminate a post-back, despite it "appearing" to not have a post-back. A page life cycle and "round trip" does occur, but only the "things" inside of the UP are posted back.
Ok, last but not least?
The question is how to use end request event?
that event is for CLIENT SIDE code, not server side.
So, in place of that register script at the end of the server side code (in update panel), we could have the UP panel ALWAYS call some client side code, and we thus eliminate the requirement to "register" some client side js code to run.
As I stated, the "use case" for this is not all that great, since we have the ability to register any script in the server side code anyway.
however, lets remove the register script code, and use the "end request" event of the update panel.
So, we do it this way:
<script>
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(mytoastmsg);
function mytoastmsg() {
btnID = $('#cmdStart').attr("id")
toastcall(btnID, "Processing Complete",
"All steps for project<br/>are now complete", "6000")
}
function toastcall(sControl, sHeading, sMsg, sTime) {
var btn = $('#' + sControl)
var btnpos = btn.position()
$.toast({
heading: sHeading,
text: sMsg,
position: {top: (btnpos.top + btn.height()), left: btnpos.left + btn.width()},
icon: 'info',
hideAfter: sTime,
allowToastClose: false,
loader: false,
showHideTransition: 'slide'
});
}
</script>
So, note the add_endRequest - that sets up the "end request" code client side. So, now for any and all "end" of the UP, that one js code stub will run.
so, our button in UP becomes this:
protected void cmdStart_Click(object sender, EventArgs e)
{
// fake 4 seconds long running
System.Threading.Thread.Sleep(4000);
//MyToast(this.Page, cmdStart.ClientID, "Processing Complete",
// #"All steps for project<br/>are now complete", "6000");
}
So, for testing, we just commented out the final script register, since now, the "end request" setup will fire + trigger the client side js code ALWAYS at the end of the post back for the UP.
the effect is 100% the same as the register script example.
This has to be the simplest thing in the world but it just isn't working.
I have an outer div to which I want to apply a class to make its display style = none so that it hides all the content within it. It's actually an asp:panel element so I'm assuming I can just set control.CssClass = "my-hidden-class" in the code behind.
I'm actually setting this on a button click handler(depending on certain conditions) But the class is never applied. When I inspect the div element in Firebug it doesn't even have a class attribute. It appears exactly as it is in the .aspx markup (the actual css class is fine & gets applied when I add it declaratively).
Also, I can see the class applied if I set CssClass in the prerender method on the initial get request. So I thought maybe I'll put all the logic in prerender and update the Css Class accordingly. This also doesn't work - the class gets applied on the initial get ok but I can't change it subsequently.
So, to sum up it seems I can't apply class from code behind at all in the event handler and I can only apply it in prerender for the intial get request & this value is persisted on all postbacks.
What am I doing wrong?
Edit: Here's the code -
aspx:
<asp:panel runat="server" ID="TariffContainer"><!--this is the div I want to toggle-->
<cms:ContentBlock ID="currentTariffsInfo" SkinID="Public/OurPrices/CurrentTariffsInfo" runat="server" />
<ucTcrPanel:tcrpanel ID="tcrpanel" PagingEnabled="true" runat="server" />
<div class="quick-price">
<asp:LinkButton runat="server" CausesValidation="false" ID="QuickEnergyPrice" OnClientClick="Javascript:return false;" CssClass="button subcontent"><span>Get a quick energy price</span></asp:LinkButton>
</div>
<div class="not-for-sale">
<cms:ContentBlock ID="preservedTariffsLinkInfo" SkinID="Public/OurPrices/PreservedTariffsLinkInfo" runat="server" />
<p>
<asp:LinkButton runat="server" CausesValidation="false" ID="ViewNotAvailableTariffs" OnClick="RedirectToUnavailableTariffs" cssclass="arrow">View tariffs not available for sale</asp:LinkButton>
</p>
</div>
</asp:panel>
Code Behind:
protected void PostCodeChange_BtnClick(object sender, EventArgs e)
{
if (IsValid)
{
tcrpanel.ApplyPostcodeUpdate(postcode.EnteredPostCode);
tcrpanel.TcrUpdatePanel.Update();
}
else
{
TariffContainer.CssClass = "formContentHidden";
}
}
Update - The button click event is coming from a user control & this is wired up to trigger an update on an update panel - i.e. a partial postback is happening. I'm doing this hiding & showing of the div in the containing aspx page & even though all the server side page events are executing I'm guessing that the content of the page isn't getting re-rendered so I'm not seeing my changes.
The Solution - I ended up squirting a bit of javascript down from the server:
protected void PostCodeChange_BtnClick(object sender, EventArgs e)
{
tcrpanel.ApplyPostcodeUpdate(postcode.EnteredPostCode);
tcrpanel.TcrUpdatePanel.Update();
}
Then in the tcrpanel user control code behind:
public void ApplyPostcodeUpdate(string postcode)
{
if (IsValid)
{
BuildStartUpScript("showTariffContainer();");
}
else
{
BuildStartUpScript("hideTariffContainer();");
}
}
private void BuildStartUpScript(string functionCall)
{
StringBuilder script = new StringBuilder();
script.AppendLine("<script type=\"text/javascript\">");
script.AppendLine(functionCall);
script.AppendLine("</script>");
ScriptManager.RegisterStartupScript(pnlUpdateTcr, pnlUpdateTcr.GetType(), "HideTariffContainerScript", script.ToString(), false);
}
Then in the included JS file:
function hideTariffContainer() {
$("div.formContentVisible").toggleClass().toggleClass("formContentHidden");
}
function showTariffContainer() {
$("div.formContentHidden").toggleClass().toggleClass("formContentVisible");
}
As suspected, the problem was that a partial postback was occurring in which only the contents of the update panel were being re-rendered.
That said, all the server side page lifecycle events were still being invoked. This is what confused me as I could debug and see the CssClass being applied but not being rendered in the html. Just the way Asp.Net update panels work I guess.
Is it possible to make a menu item behave like a button? By this I mean that instead of setting the NavigateUrl property to a new page, assign a method when the item is clicked?
You can add a click handler for the menu.
The MenuItemClick tells you which item was clicked.
<asp:menu id="NavigationMenu"
onmenuitemclick="NavigationMenu_MenuItemClick"
runat="server">
You could take action depending upon which item was clicked by the user.
void NavigationMenu_MenuItemClick(Object sender, MenuEventArgs e)
{
if (e.Item.Text == "MyItem")
{
//do some processing
}
}
Ofcourse you can do it..you can call a server side function using__dopostback() for example
on your menu item's click you can call this Javascipt function
<script type="text/javascript">
function SaveWithParameter(parameter)
{
__doPostBack('btnSave ', parameter)
}
</script>
Try the below:
<asp:menuitem navigateurl="javascript:YourJScript()"
If you need to execute a method in serverside, use a hidden variable, then set a flag in javascript method and submit the page.
In serverside, check the flag in page load and call the method as required.
Thanks
<td><input type="image" style="border-width:0" alt="Do an Edit" title="Edit the repeater row" tabindex="0" src='<%=ResolveUrl("~/css/image.png") %>' onclick='showModal(<%#Container.ItemIndex %>); return false;'/></td>
I am already using onClick() for invoking a javascript method. Now, I want to add another an event to this element to trigger a server side event- say using onKeyUp- and pass 1 parameter on the repeater to the server side.
Is this possible or I have to first call javaScript and then Javascript on the page will callinto my server side. (I think this way the method in the server side code has to be static).
You can add an invisible LinkButton to your page (for example LinkButton with a blank text) and from your client-side onKeyUp event call LinkButton's click() method and catch Click event server side.
To pass parameter you can use any control that is readable both client-side and server side, for example hidden field.
For example - your HTML markup can look something like this:
<asp:TextBox ID="xtxtMyText" runat="server" onkeyup="doMyPostback()"></asp:TextBox>
<asp:HiddenField ID="xhidParam" runat="server" />
<asp:LinkButton ID="xlnkMyPostBack" runat="server" OnClick="xlnkMyPostBack_Click"></asp:LinkButton>
<script type="text/javascript">
function doMyPostback(e) {
var evt = window.event ? window.event : e;
if (evt.keyCode == 13) {
document.getElementById('xhidParam').value = document.getElementById('xtxtMyText').value;
document.getElementById('xlnkMyPostBack').click()
}
}
</script>
Here you have a textbox that triggers keyUp event, hidden linkbutton that causes server-side Click event and hidden field that is used to pass parameter. In this scenario if user hits Enter, content of textbox is copied to the hidden variable and the linkbutton is clicked.
On the server side you can handle that event and read the passed parameter from the hidden field, e.g.
protected void xlnkMyPostBack_Click(object sender, System.EventArgs e)
{
Response.Write(xhidParam.Value);
}
How do I execute Javascript after submission of an ASP.NET form?
For example, if I got a submit button click after submission of page then I want to display a DIV which I have hidden on page.
Since you are using a full postback, you can easily include the javascript from the code-behind.
Place your JavaScript Code inside a Placeholder
<asp:Placeholder ID="javascriptPlaceholder" runat="server" Visible="false">
<%-- Your Javascript here -->
</asp:Placeholder>
I assume in your OnClick handling method, you are getting the value of the form and do something else with it. In this method you could set the Visibile property of the placeholder:
this.javascriptPlaceholder.Visible = true;
If you would only want to convert the hidden div to a visible one then that can be done on the server side. In the aspx, give the div an id and a runat="server". Then in the server side, set its display style attribute to 'block'. For example, say the div is defined as
<div id="divTest" runat="server" style="display:none;">
This is a div test
</div>
Then in the post event of the submit button you can set its style as given below:
divTest.Style["display"] = "block";
If you only want to emit scripts after the post then using the ScriptManager you could use:
ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "ScriptRegisterTest", "alert('Testing');", true);
Maybe I'm not understanding your question, but if you're going back to the server and doing some processing, why do you need javascript? Just add a runat="server" to the div in question and make it visible after the processing.
<div id="YourDiv" runat="server" Visible="false" >
...Whatever is here
</div>
Code Behind:
protected void Button_Click(object sender, EventArgs e)
{
/*
Your Logic Here
*/
YourDiv.Visible = true;
}