I researched this problem here on SO and tried the apparent solution which did not work, so here it is:
I have a very complex form with among other controls, three autocompleting textboxes.
I also have a client who cannot seem to stop entering a value in the textboxes and hitting the Enter key to select the desired value from the autocomplete list.
When they hit Enter, the first imagebutton in the form fires, doing something completely different. So to them, the form is broken.
What I need to do is to prevent the Enter key from firing these imagebuttons (there are 10 of them in the form).
I have tried the following code in both Page_Load and Page_LoadComplete, neither of which work:
imgbtn1.Attributes.Add("onkeydown", "return (event.keyCode!=13);")
Any advice that saves me a few hairs is appreciated.
One good solution can be found here:
Disable Button click, ImageButton click and/or form submit on Enter Keypress
Adding Markup from Link
<form id="form1" runat="server">
<input type="submit" style="position:absolute;left:-100px;top:-100px;width:0px;height:0px;" onclick="javascript:return false;" />
<!-- other form controls below this line -->
</form>
Did you check these two references
http://www.bloggingdeveloper.com/post/Disable-Form-Submit-on-Enter-Key-Press.aspx
http://www.webcheatsheet.com/javascript/disable_enter_key.php
They are essentially doing the same thing you are trying, just that they are hooking it up to a different event. Also make sure that your Javascript is foolproof i.e. if javascript has some errors, then your end result may not be as expected.
The second link Subhash Dike posted (Disable Enter Key) worked for me. I have two ImageButtons and they both don't fire a postback when using this function (bit modified from the original) which is great.
document.onkeypress = function (evt) {
return ((evt) ? evt : ((event) ? event : null)).keyCode != 13;
};
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.Page.Form.DefaultButton = BtSearch.UniqueID
If Not IsPostBack Then
' ...............
End If
End Sub
I had a similar problem.
Listview1.ImageButton was responding to ENTER.
We really want a SAVE to happen (or nothing, but the bad behaviour was reloading the page and that made them grumpy)
Set up a handler for the window to catch events. I do this in docReady()
function docReady() {
$(document).keydown(mapKeyCode);
};
In that handler, find the keycode you want to capture ( enter is 13)
https://css-tricks.com/snippets/javascript/javascript-keycodes/
function mapKeyCode(event) {
{
if (event.keyCode == 13) {
//event.stopPropagation();
//event.preventDefault();
__doPostBack('ctl00$cp1$InventoryPieces$btnSubmit', '');
}
}
event.StopPropogation will cause nothing to happen.The keystroke is simply eaten. That may be what you want. You are still free to call an ajax method below, that's not part of the event.
event.PreventDefault is supposed to stop the event from doing what it normally does. I had troubles seeing a difference w/ this line commented out or not. There is in depth discussion on preventDefault and ENTER here on SO.
This 3rd line is what the people who pay me want to have happen when they hit the ENTER key even though they probably should be hitting tab. I tried (#).trigger() and didn't have a lot of luck. Inspecting the element, I saw that it was calling __postback, so I pasted that in. I'm reasonably certain ().Trigger would work if i figured out what i was doing wrong, I just took another route.
This is hackish to me, but it accomplishes the objective.
Hope it helps.
Related
I have an asp:Button that fires a code behind function on the OnClick event. In that OnClick event several things happen, and among those things I do a check in the database for if I need to ask the user a yes or no question. For that I need a message box. First I did it like this:
protected void MyButton_Onclick(object sender, EventArgs e)
{
// lots of stuff happening
bool iNeedToAskTheUser = INeedToAskTheUser(stuff);
if (iNeedToAskTheUser)
{
DialogResult result = MessageBox.Show("Do you want to fix all objects?", "Fix objects", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes) // do stuff
}
// some other stuff
}
This works fine locally but not when deployed, so I figure I would need to use ScriptManager.RegisterStartupScript instead. I could just add javascript on the ASPX page that fires up a dialog and saves the response in a hidden control that I can then look at, but I don't want to fire up the dialog unless I have to, which I check for before I do the DialogResult in the code above. So I can't do that immediately when the user clicks the button.
Is there any way I can use ScriptManager.RegisterStartupScript in "the middle" of my _OnClick code so that I can choose whether or not to actually show the button, and then also know if the user clicked yes or no, (preferably) without doing a postback?
I've been thinking and testing two different solutions:
Use ScriptManager.RegisterStartupScript in code behind to fire a JavaScript confirm function on the ASPX page. The JavaScript function would set a value in a hidden control depending on if the user answered yes or no and then my code behind stuff would check the value of that hidden field and act upon that. The problem with that is that once ScriptManager.RegisterStartupScript fires it doesn't wait for the JavaScript function to "finish", ie wait for the user to reply to the confirm(). So the value in the hidden control will always be empty because the code behind gets to the check of that control before the user has a chance to respond to the confirm(). So that's a no go.
Use ScriptManager.RegisterStartupScript in code behind to open up a new ASPX page that asks the user the question and then does all the work in response to the user's answer in that page. The problem then is to pass the object that the new ASPX page needs to do work on in response to the user's response.
I'm sure there are great solutions using Ajax or jQuery but this is a fairly simple function that shouldn't take too long to develop, so that is kind of out of scope for this.
Instead I'll go with a solution where I know what the user will respond to the question before they click the button. (While silently muttering under my breath: "It's 2019 and there's no good way to fire up a yes/no dialog from code behind in a .Net web project...". I need to get back to not working with web).
I have the following simple test asp.net form, with following vb.net load event:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim strScript As String
strScript = "function MyMsg()"
strScript += "{"
strScript += "alert(document.getElementById('TextBox3').value);"
strScript += "}"
ClientScript.RegisterStartupScript(Me.GetType(), "MyMsg", strScript, True)
End Sub
It simply displays the contexts of a text box in the web page when the script is called.
I then have this button code:
Protected Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
If ClientScript.IsStartupScriptRegistered("MyCall") Then
Me.TextBox3.Text = "My text - registered"
Else
Me.TextBox3.Text = "my text NOT registered"
End If
ClientScript.RegisterStartupScript(Me.GetType(), "MyCall", "MyMsg();", True)
End Sub
However, the button when clicked on always shows the text NOT registered. So, the code seems to run ok. It grabs the text from the text box no problme. However, the True part of the code never runs.
Is this a state or scope issue? (or the the fact that the code is only injected one time) that prevents this from running the code block for true?
How can I get the "true" part of the above code to run?
Consolidating(and elaborating on) the comments on the original question here.
The issue is that ASP.NET buttons cause full post backs to the server everytime they are clicked and when a page does a full postback it resets all scripts that may have been registered from previous actions. This means that any script that was registered the last time the button was clicked will be wiped out and the page will not know anything about it the second time around.
There are a few ways to get around this.
UpdatePanel: My prefered way is to declare all your controls that need to be manipulated in the button click handler inside an AJAX Update Panel like:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<asp:Button ID="Button1" runat="server" Text="Button" />
</ContentTemplate>
</asp:UpdatePanel>
What this does is limits what the button can change when it is clicked and causes a post back. In order to use this you will also need to declare a Scriptmanager anywhere before the updatepanel. When you register the script you will need to use that scriptmanagers RegisterScriptControl function.
Manual AJAX Postback: Another way to accomplish this would be to use a "manual" AJAX call. I've done this a few times but it is much more complex than the update panel version and I'm not sure if the way that I've done it is the "right" way to go about it. First you will change you ASP button to a regular HTML input button. On the HTML button the onclick should be a javasciprt function that you designate. Inside the javascript function you will need to go through the process of declaring an XMLHttpRequst object. This site goes over how to use the object pretty thoroughly. The way that I have gotten information back and forth is by using the headers attached to the request/response. You need to add them using setRequestHeader function and get them from the getAllResponseHeaders function. Once you get into the page load event on the server side you will need to evaluate the headers of the request and if one exists that signifies that the button was clicked(which you will need to add manually) then you can call a function and add a header to the response that will tell the javascript what to display in the pop up box. I'm sure using headers isn't the best method for getting inormation back and forth but if you are just talking about booleans that only dictate what to print to the user then you probably don't need to go through the process of setting up a JSON or XML response. This is also assuming that you are doing more on the server side than just checking how many times the button has been clicked because if thats all you need to do you should use option 3.
The simplest way to accomplish this would be to make the entire thing a javascript function. Declare a variable(int) on the page and set it to 0 on load. Then when the button is clicked you would just need to check the counter, if its greater than 0 display one message, if its 0 then display a different message. This will only work if your condition is very basic(it can get very complex but sometimes thats overkill).
So, In my opinion, those three options should be able to handle whatever you need to do. The first is very simple to use, the second is very versatile and can become very powerful if you implement XML or JSON in your communications with the server and the third is much faster than communicating with the server every time. Deciding which will be the best fit is up to you.
You did not add the script tag to enclose your script.
Adding function
strScript = "<script type=\"text/javascript\">";
strScript = "function MyMsg()"
strScript += "{"
strScript += "alert(document.getElementById('TextBox3').value);"
strScript += "}"
strScript = "</script>";
ClientScript.RegisterStartupScript(Me.GetType(), "MyMsg", strScript, True)
Calling function
ClientScript.RegisterStartupScript(Me.GetType(), "MyCall", "<script type=\"text/javascript\">MyMsg();</script>", True)
What is this keyword how can use it?
If Page.IsPostBack = False Then
IsPostBack
Here is an overview of IsPostBack from MSDN:
http://msdn.microsoft.com/en-us/library/system.web.ui.page.ispostback.aspx
It quotes:
true if the page is being loaded in
response to a client postback;
otherwise, false.
The postback is useful, say for example you have a Literal control on the page, and the code on page load sets the Literal.text += "hello"; If you have a button on that page, and press it, the text of the literal will get longer and longer, hellohellowhello, if you wrap the code in (c# example):
if(!Page.IsPostBack){
Literal.text += "hello";
}
The Literal text now wont expand when the button is pressed.
Other Notes
Instead of:
If(Page.IsPostBack = False)
Do:
If(!Page.IsPostBack)
This is logically the same and is generally accepted to be a better way of writing the statement.
Also you marked the question C#, but the If syntax you used indicates you are writing it in VB.net, not C#.
Gets a value indicating whether the page is being loaded in response to a client postback, or if it is being loaded and accessed for the first time.
Return Values:
true if the page is being loaded in response to a client postback; otherwise, false.
http://msdn.microsoft.com/en-us/library/system.web.ui.page.ispostback.aspx
The IsPostBack tells you whether or not the page has been Posted Back, meaning "server side" button has been clicked.
You can "use" it by reading its value and acting upon it.
It's useful for example when you add controls dynamically to your page, so you don't have to add them when it's a PostBack.
Official documentation already been posted by others, look there for any further or technical details.
I have a situation where I need to ignore parts of page load sub inside a isPostback = true. Basically inside the isPostBack I want something like if button1 caused postback.... do this else do this...
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = True Then
If TextBox1.Text <> String.Empty Then
CheckDate()
End If
End If
End Sub
I think what you need is the reference to the control name which triggered the postback.
http://geekswithblogs.net/mahesh/archive/2006/06/27/83264.aspx
Implement the solution which is there in the above link (Got it from here.... How to Get Source of postback)
If the control name is your button then do not do what needs to be done upon postback.
HTH
You should probably not have all this going on inside the Page_Load event. Instead, you should be handling events for each control that can cause a postback. This helps with code clarity, and ease of maintenance, not to mention better control in the first place.
Here's a nice brief blog entry I found on the subject: http://www.sitepoint.com/blogs/2007/01/21/page_load-is-evil/
Incidentally, handling events is much different in ASP.NET than in other environments, My guess, just based on the fact that you're trying to accomplish this in the Page_Load event is that you're not yet "getting" the event-driven programming model. (If I'm wrong, I apologize, I don't mean to be insulting).
If I'm right, however, once you get used to it, it's going to be a lot simpler for you than things were in the classic ASP days, for example, where you had to do things like try to figure out which button was clicked. Here's another nice article to explain this further: http://articles.sitepoint.com/article/driven-asp-net-development-c
It's hard to see this as a good idea. From the short snippet you posted, it looks like what you really need is a Validation control attached to your textbox.
Have a look at the POSTed items. You should see some sort of reference to that button in there. IIRC, if it was clicked, you will see some sort of reference in there, and if it wasn't it wouldn't be in there.
I had this same problem a while a ago and that's how I circumvented loading some stuff.
I am trying after the btnCreate_OnClick event to reset the form to it's default value just like the first page_load. The problem is after PostBack, every textbox and other controls, reloads the ViewState value. I cannot deactivate viewstate because of server event on DropDownList selection. The only way I found so far is to Redirect to self after the click event, but this loads the page twice and is therefor a bad solution. I have try ViewState.Clear() and update the UpdatePanel, but was unsuccessful.
I could do a loop for all controls and set the txtXXXXX.Text == "", but I'm quite sure it's not the best idea.
Something like Page.Reset() would have been just perfect but it doesn't exist.
Any thought on this problem of mine?
Thanks
If workable, I usually just use Response.Redirect to reload the same page from scratch.
An initial GET request to a page usually costs less than subsequent POSTs anyway, so there's not much reason to avoid it.
We can reset the ASP.NET Form Page with just 2 lines of code
protected void Button_Reset_Click(object sender, EventArgs e)
{
Session["ViewState"] = null;
Response.Redirect("/Roster/DRAC/Create.aspx");
}
Self redirecting gets tricky because of viewstate.
There is an html input type "reset" for buttons, but I'm not sure what or any integration msft has put into viewstate/asp.net for this. It generally works for simple javascript forms.
ex:
<input type="button" value="Reset" onclick="document.<formId>.reset();">
from google ----^
One way, not necessarily ideal, is to reset the values to their defaults using Javascript. If it is a large form, it can be ugly, but will prevent the need to do a self-redirection.
You also might try Server.Transfer instead of Response.Redirect(/self/)
I dont know if this helps but i change the name of every input on the form that i want to get fresh values by using javascript before submiting the form, since the .net page can no longer match the values from the form to the controls for the page it reloads them as if there was no postback. i also append a new value to the form so i know what button submitted the form and use that logic to decide what to load into all the controls and how to process the form data of course.
$("#Bset").children().click(function() { //all the btns click function
$.each($("form").find("input"), function(e,v) { //could filter this to subset of inputs
$(v).attr("name", "_" + $(v).attr("name")); // ctrl1 becomes _cntrl1
});
$("form").append("<input type='hidden' id='b' name='b' value='" + $(this).text() + "' />").submit();
});
then in the code behind
protected void Page_Init(object sender, EventArgs e)
{
id = int.Parse(Request.QueryString["id"]);
bk = db.dc.getDetailBK(id).Single();
if (Request.Form.Count > 0)
doPostBack();
mrl = (from a in db.dc.getMetricQTD(id, null, null, loadSavedGoals) select a).ToList();
}
i can then do things in dopostback that process the form data, interact with the db etc. that may change the values mrl is loaded with and refresh the data in the inputs tied to mrl regardless of wether they were modified or not on the form.
the other alternative would be to tie some buttons to use a webservice to handle your db interaction then call window.location to refresh the page.
$.ajax({
url: "webservice/dbfunction?"
data: {which btn pressed, some form values etc...}
success: function() {window.location("samepage.aspx?id=xxx");}
...
});
this would also avoid having to response redirect on the server side.
In our case the best performance solution was to set manually for each control the default value in the click event ex:
textbox1.Text = null;
textbox2.Text = null;
This avoid the double page_load and the loop. We don't event have to update the UpdatePanel since it executes before render.
Maybe in a more complex web application we would have to Redirect as most people seem to accept this as a solution.
Setting per control the default value was better suited to our case.
Thank you