I am using AJAX in asp:net and am trying to handle a situation where an asp:button triggers both a javascript method and a codebehind c# method. To do this I am using onclick and onClientClick attributes for the button. I need a postback to occur for the codebehind to be called however this postback causes the javascript to not work because variables have lost state. Can anyone describe how to handle this? Possible with ajax and async postbacks? It's starting to drive me a bit crazy!
Edit:
The javascript is actually for a google-map (v3), the c# code is for submitting to an sql db.
The map is initialized in the code-behind with:
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack) {
ScriptManager.RegisterStartupScript(this, this.GetType(), "onload", "initialize_map();", true);
submitButton.Command += new CommandEventHandler(this.submitButton_Click);
}
}
Here is some of the relevant code:
<asp:UpdatePanel runat="server" ID="Form" UpdateMode="Conditional">
<ContentTemplate>
(...form stuff...)
<asp:Button ID="submitButton" runat="server" Text="Submit" ValidationGroup="NewCallFormSubmit" OnClientClick="calcRoute(); return false;" onclick="submitButton_Click" />
</ContentTemplate>
</UpdatePanel>
<asp:UpdatePanel runat="server" ID="DisplayUpdatePanel" UpdateMode="Conditional">
<ContentTemplate>
<h1>
Pick-Up and Drop-Off Locations
</h1>
<!-- Map Layout -->
<div id="map_canvas" style="width: 500px; height: 500px;"></div>
</ContentTemplate>
</asp:UpdatePanel>
...I think it would work if I could get the first updatepanel to postback on the button click, the second panel not to postback, and the button to still call the codebehind. So far no luck with this all happening at the same time.
If you simply want to run your OnClientClick (client) code before your OnClick (server) code, try the following:
ASP.NET
<asp:Button ID="btn_mybutton" runat="server" Text="MyButton" OnClientClick="return JSFunction();" OnClick="CFunction"/>
Javascript
<script type="text/javascript">
function JSFunction() {
alert('Some JavaScript stuff');
return true;
}
</script>
C#
protected void CFunction(object sender, EventArgs e)
{
// Some server code
}
The JavaScript function is executed first and returned from before the server code is executed.
Related
My updatePanel is in MasterPage and FileUpload is in Child Page.
As FileUpload requires a full PagePostBack I tried following approaches, but none of them worked, fileupload.hasfile gives false and postedfile is null. Not sure what else to do. Please go through and suggest. Is there anything that I am missing.
Using .NET Framework 4.0, Bootstrap 4
Approach 1 - Adding Postback trigger through code behind
AddTriggers(btnupload.UniqueID);
public static void AddTriggers(string ControlID)
{
UpdatePanel UP = Page.Master.FindControl("MainUpdPanel") as UpdatePanel;
UpdatePanelControlTrigger trigger = new PostBackTrigger();
trigger.ControlID = ControlID;
UP.Triggers.Add(trigger);
}
Approach 2 - Wrapping fileupload and it's button in a separate UpdatePanel in child Page
<asp:UpdatePanel ID="Upld" runat="server">
<ContentTemplate>
<div class="input-group form-inline">
<asp:FileUpload ID="FileUploadreq" runat="server" />
<asp:Button runat="server" ID="btnupload" Text="Upload" OnClick="btnupload_Click" />
<asp:LinkButton runat="server" Text="View" ID="lnkview" OnClick="lnkview_Click" Visible="False"></asp:LinkButton>
</div>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="btnupload" />
</Triggers>
</asp:UpdatePanel>
Add enctype="multipart/form-data" to the form tag and add the trigger in your page Page_Init function
protected void Page_Init(object sender, EventArgs e)
{
AddTriggers(btnupload.UniqueID);
}
I have that example:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<fieldset>
<legend>UpdatePanel</legend>
<asp:Label ID="Label1" runat="server" Text="Panel created."></asp:Label><br />
</fieldset>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1" />
</Triggers>
</asp:UpdatePanel>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" /></div>
protected void Page_Load(object sender, EventArgs e)
{
// doesn work with:
Response.Write("eg.");
}
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "Refreshed at " + DateTime.Now.ToString();
}
This works fine. When I click in the Button the Label updates without refreshing the page, but if I have Response.Write in the Page_Load event, when I click the button the UpdatePanel doesn't work, and I need the Page_Load.
How I can solve my problem? Thanks.
Don't use Response.Write() in your Page_Load function, as it will break the UpdatePanel.
In fact, using Response.Write() is often a bad idea, because you don't control where in the DOM the written content will end up. Instead, if you need some simple debug output, then use other means such as System.Diagnostics.Debug.WriteLine(). Or if you need to add something to the DOM, add a control such as Label and manipulate that.
I have a simple JQuery enabled ASP.NET page:
<script>
$(document).ready(function() {
$("#accordion").accordion();
});
</script>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div id="accordion">
<h3><a id="Accordion1" href="#">Accordion Panel 1</a></h3>
<div>
A form input...
<asp:Button id="btnSubmit" runat="server" onclick="btnSubmit_Click" />
</div>
<h3><a id="Accordion2" href="#">Accordion Panel 2</a></h3>
<div>
Some content...
</div>
</div>
</ContentTemplate>
</asp:UpdatePanel>
If you'll notice, I'm using an UpdatePanel also.
btnSubmit_Click event does something like this:
protected void btnSubmit_Click(object sender, EventArgs e)
{
//Some MySql INSERT, etc.
}
Now what I want to do is for server-side btnSubmit_Click to trigger JQuery to "click" Accordion Panel 2 (so it will open Accordion Panel 2 and close 1). How to do this?
UPDATE: Sorry guys I forgot to mention earlier that It's got an UpdatePanel
Oh well, I just used the "change the value of a hiddenfield after postback then let jquery read that hiddenfield" approach. Thanks guys!
Jquery:
var tag = $("#contentBody_hfTag1").val();
if (tag=="1") { $(".Accordion").accordion({ active: 1 }); }
else { $(".Accordion").accordion({ active: 0 }); }
.aspx
<asp:HiddenField ID="hfTag1" ClientIDMode="Predictable" Value="0" runat="server" />
C#
protected void btnMyButton_Click(object sender, EventArgs e)
{
hfTag1.Value = "1";
}
You can't. Jquery runs on the client, your handler is on the server. You will need to trigger the event on the client when the page reloads after the post back.
You can't do that as Jquery works on client side, from a server side event, as the page reloads. And the state of the accordion will be lost. So what you can do is, instead of making a post back, you can do the same work in a Jquery AJAX call on the button click to do whatever you want and then close the accordion 1 and show accordion 2.
<asp:UpdatePanel ID="up1" runat="server">
<ContentTemplate>
<i88:InlineScript runat="server">
<script type="text/javascript">
$('Accordion2').click()
</script>
</i88:InlineScript>
<asp:Button ID="cmd" runat="server" Text="Update" />
</ContentTemplate>
</asp:UpdatePanel>
You can put inlineScript which will get Executed every time you update the Panel.
You can also use jQuery.Trigger(); for other event's.
On a ASP.Net page, I am in front of a problem only with IE. Here is the description.
On a page, there is two buttons and one label. The first button is visible and calls a JS function on the click event. This JS function calls the click function of the second button. The second button has an C€ event handler on the click event. The C# event handler edit the label.
In Firefox : the label is correctly edited after the clicks.
In IE (8) : the label is not edited, despite the C€ event handler has been correctly hit.
Also, I observed, in IE, that the Page_Load event is called two times after the JS button click :
Page_Load
button2_OnClick => change of the Label Text
Page_Load => The Label Text is reset :(
In Firefox, the Page_Load is called only once.
My question is : how to make IE refresh correctly the page as Firefox does after a JS button click ?
Below is the sample test code :
1) Page ASPX
<head runat="server">
<title></title>
<script type="text/javascript">
function button1Click(sender, args) {
var button2 = document.getElementById("button2");
button2.click();
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button runat="server" ID="button1" Text="Click-me!" OnClientClick="button1Click();" />
<asp:Button runat="server" ID="button2" Text="Second" OnClick="button2_OnClick" style="display:none" />
<p />
<asp:Label runat="server" ID="label1" Text="Init" />
</div>
</form>
</body>
</html>
2) C# code-behind :
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void button2_OnClick(object sender, EventArgs e)
{
label1.Text = "Changed";
}
}
The ID of your button will not be button1 or button2 when it's rendered. It will probably be something like ctl001_button1. Therefore your javascript will not work. In ASP.NET 4 you can override this behaviour by using an assigned ClientID.
<asp:Button runat="server" ID="button1" Text="Click-me!"
OnClientClick="button1Click();" ClientIDMode="Static" />
<asp:Button runat="server" ID="button2" Text="Second"
OnClick="button2_OnClick" style="display:none" ClientIDMode="Static" />
As an aside, this alludes to the main problem with ASP.NET Winforms - it tricks developers into thinking that the web is a connected environment.
What actually happens when you click an <asp:Button /> element by default is that a postback is invoked. I.e. Your browser sends a request to the server for a new page. It sends up something called ViewState which is how the server knows what you've done and what to render. There is no "event" handled as such.
I think the problem is with the way you are trying to get the hidden button
var button2 = document.getElementById("button2");
maybe change this to
var button2 = document.getElementById("<%= button2.ClientID %>");
After the buttons are rendered in the browser, the ID is changed by the ASP.Net engine, and not the same as your source.
http://msdn.microsoft.com/en-us/library/system.web.ui.control.clientid.aspx
Hope this helps.
I have a master page that contains an image as follow:
<asp:Image ID="imgCompanyLogo" runat="server" ImageUrl="image path" />
and in a child page I want to edit the property ImageUrl as follow:
Image imgCompanyLogo = (Image)Page.Master.FindControl("imgCompanyLogo");
imgCompanyLogo.ImageUrl = ResolveUrl("~/images/CompanyLogo/Logo.png");
and it doesn't give me an exception, but it doesn't change anything.
Note: I have an UpdatePanel in the child page.
Since the image is sitting outside of the UpdatePanel, server side changes will not be executed on the image after a partial postback. Your only option is to inject JavaScript into the page and change the image URL.
Use the ScriptManager.RegisterStartupScript Method to inject JavaScript after the partial postback.
Something like the following will work for you:
C#
protected void btnPostback_Click(object sender, EventArgs e)
{
imgCompanyLogo.ImageUrl = ResolveUrl("~/images/CompanyLogo/Logo.png");
ScriptManager.RegisterStartupScript(btnPostback,this.GetType(), "myScript", "ChangeImage('" + ImageUrl + "');",false);
}
JavaScript
function ChangeImage(imgURL) {
//make sure the ID of the image is set correctly
document.getElementById('imgCompanyLogo').src = imgURL;
}
Wrap image by UpdatePanel with UpdateMode="Always"
Master Page:
<asp:UpdatePanel runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:Image runat="server" ID="Image1" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
public void SetImageUrl(string url)
{
Image1.ImageUrl = url;
}
Child Page:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:Button Text="Click Me" runat="server" OnClick="UpdateImage" />
</ContentTemplate>
</asp:UpdatePanel>
protected void UpdateImage(object sender, EventArgs e)
{
((Main)Master).SetImageUrl("~/Images/0306d95.jpg");
}
The code above works well for me.
Have a look at Sys.WebForms.PageRequestManager Class. Define handler in javascript and may change the image source.
If your code is being run after an async postback (per your UpdatePanel) then changes to anything outside the UpdatePanel will not be rendered. Content in the master page would definitely seem to qualify.
If this is what you're trying to do, this model won't really work. You will need to use some client script to effect changes to already-rendered content when working with this model.
An UpdatePanel is a construct to identify an area that's updated through ajax. The page is not actually reloaded. So an postback can never change content that's outside of the UpdatePanel (or control bound to that panel) that sourced it.
Here's a basic implementation (using jQuery). Add a hidden field to pass the new source to the client. This must be inside the UpdatePanel. Change this value from the server when you want the image to update with new_image_src.Value=ResolveUrl(...);
<asp:HiddenField ClientIdMode="Static" runat="server" id="new_image_src"
value="" EnableViewState="false">
Give your image a static id too to make life easier:
<asp:Image ClientIdMode="Static" runat="server" id="dynamic_image" ImageUrl="..." >
Add javascript to the page (should NOT be in the UpdatePanel):
function updateImage() {
var new_src=$('#new_image_src');
if (new_src) {
$('#dynamic_image').attr('src',new_src);
/// erase it - so it won't try to update on subsequent refreshes
new_src.val('');
}
}
$(document).ready(function() {
/// adds an event handler after page is refreshed from asp.net
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(updateImage);
});
This wouldn't be difficult to do without jquery either but seems more common than not these days.