I have a table that is created in a DataList in ASP.Net. This table has three fields of text, then a field with an edit button, and a field with a delete button. When a person clicks the delete button, it posts back, deletes the items, and then binds the DataList again. The DataList is in an UpdatePanel so the item smoothly disappears after a half of a second or maybe a little more, but what I'd really like is for the row to slide out (up) as soon as they hit the delete button, and then have it delete the item on the post back.
I can make the row slide out with jQuery, but the postback gets in the way. How do you deal with that?
You can use page methods in asp.net to send a request to the server without doing a postback. They are very simple to use and you can do whatever effect you like when the ajax call is completed (you get a function called on success).
If you want to stick with the post back one solution is the following:
<asp:Button id="myButton" OnClientClick="return fadeThenAllowSubmit()" ... />
and in js something like:
var allowSubmit = false;
function fadeThenAllowSubmit() {
if (allowSubmit) return true
// do the jquery stuff that will be completed in, let's say, 1000ms
setTimeout(function() {
allowSubmit = true
$("input[id$=myButton]").click()
allowSubmit = false
}, 1000)
return false
}
It's a bit of a hack, the idea is to cancel the postback initially, do some stuff then set a timer where the postback will be enabled. The big problem with this approach is that the fade effect and the actual delete are independent (in case of an error you still get the fade effect).
have you tried looking at any of the Ajax control toolkit items? I believe there are some controls in there that will head with client side (java) code if your not extremely familiar
I would use client side Javascript to manually scale the "opacity" CSS property down to zero, then mark the element as "display: none" then submit the post-back.
I believe that in Internet Explorer, you need to use the "Filter" CSS property to do this as it does not support opacity.
You could just code up a routine to set both properties and that should cover all the major browsers.
Register the handler for form "submit" event.
$("form").submit(function() {
// if user initiated delete action
// do your thing with deleted row (effects, etc.)
// after you're done with it, submit the form from script
// (you can queue the submission after the effect)
// the submission from the script won't trigger this event handler
return false; // prevent submission
}
Preventing form submission is necessary to avoid interference with the effects you want to perform. After they are finished, you are free to proceed with submission.
Related
I have the following scenario:
UserControlA contains a <asp:Button id="bSomeid" onClick="AddItem" /> with some code to an item to a shopping basket in AddItem.
UserControlB contains some LinkButton's that dynamically add a selection of UserControlA to the page in the OnClick event.
This is all done in an UpdatePanel. It is a little more complicated but I have pruned the information to what I believe is causing the problem, I will add more information if necessary.
The problem I have is that it takes 2 clicks for the AddItem event to trigger after I have added the items to the page after clicking the LinkButton.
I understand why this is happening - it is to late in the page cycle to register events for the next post back in the onclick - but can anyone think of a way around this? Can I force an event to be triggered on the next postback? I have tried to think of a way to run my code in page_load but I requuire access to the sender in the onClick.
Using .NET 4.0.
EDIT
I managed to find a way to get the link button sending the request in the Page_Load (using Request.Form["__EVENTTARGET"];) so I moved my code to the Page_load event. It still requires 2 clicks so I am assuming it isn't something to do with the onClick being registered to late.
Are there any other general things to check that could cause a button to require 2 clicks to post an event properly?
If your suspicion about being late in page life cycle is true then you can try using ScriptManager.RegisterAsyncPostBackControl method to register dynamically added controls in the link button click - considering that your button is within user control, you need to add public method into UserControlA that would actually register the button bSomeid1 and link button click from UserControlB would actually call the A control's method.
EDIT :
Another cause for button click not happening can be that button being dynamic control is not added in the page hierarchy when post-back happens (or it gets added very late in the page life cycle when the post back data is already processed). A really full-proof solution should add dynamic controls back to the page hierarchy in page_load it-self (and strictly maintaining same controls ids within hierarchy). If that's not possible then you can sniff the request (Request.Form) to detect the post-back.
In your case, you should ascertain if the button is indeed causing the post-back on each click. If yes, what is the POST data (Request.Form) for the first request - what is the __EVENTTARGET value on the first click (and post-back)? That should start your trouble-shooting.
On the other hand, a simple work-around could be to use html anchor element (you can still use link button) and have a javascript handler in the click event that would set some hidden variable and then submit the form (you can simulate the click on hidden button to trigger ASP.NET client side submit pipeline) . Now the hidden variable value can be used on the post-back to determine which link button has been clicked.
"Are there any other general things to check that could cause a button to require 2 clicks to post an event properly?"
Does it require two clicks on the control, or does it take accept a single click elsewhere on the screen, and then fire first time with a single click on the control?
I have my own (similar) issue with the Updatepanel where the first (expected) trigger does not fire and it seems that a single click elsewhere, and then the subsequent triggers fires first time (which totals 2 clicks)
[edit] Since you are working on this ATM, it may help me as well. Do you have a textbox with a trigger event on it? I do, and if I leave this blank (so that it does not fire) then there is no need for a second click.
I have a form page that opens a dialog in order to enter new information. I open the dialog in the "standard" jQM way:
Open dialog
What I need to do is pass back some of the values that were entered so that I can update the page with those values. How do I do that?
As an added bonus, I also really need to be able to submit the values. It seems like jQuery Mobile is setup close the page on any link click. This is an ASP.NET application, and so I need for the page to last long enough to hit the Button_Click() event in the code behind.
Here's the pieces you need:
Html in the dialog:
Cancel
Submit
In pagecreate:
$("#btnSave", pagediv).live('click', function () {
var s = page.Model;
s.serverName = $("#txtName", pagediv).val();
s.Save(function () {
$('.ui-dialog').dialog('close');
});
});
s.Save is a function that writes to the datastore, updates a global model object that is accessible to all pages, then calls the callback function.
In the pageshow handler for the parent page, update the controls from the model. You can't update the parent page directly from the dialog as the parent page may not exist at that point - if data-dom-cache isn't set, it will be removed as soon as the dialog is displayed and will not be recreated until you call close.
Now I could be going about this the wrong way so if there is a better solution please post that as well. What I am trying to do is disable a button once it is clicked to prevent double clicks. In the past I have done my just disabling the button onclick but with webforms I am running into a little bit of a snag because there is validation on the page so I need that to fire and I need to post back.
So I have the following JQuery function to make a button disable itself on click. Here is the JQuery:
jQuery.fn.disableOnClick =
function()
{
return this.each(function()
{
$(this).click(function()
{
$(this).attr('disabled', 'disabled');
return true;
})
})
};
Intended usage would be:
$(document).ready(function()
{
$("#<%= btnSomeButton.ClientID %>").disableOnClick ();
});
This doesn't work... the button always disables, the validation is ignored and the postback doesn't even happen. I would assume because I am overwrittin the click handler. Suggestions?
UPDATE: I have tried just a basic function that is connected to the 'OnClientClick' of the button to do:
// In my Page_Load
btnSomeButton.OnClientClick = "return DisableButton('" + btnSomeButton.ClientID + "');";
// Javascript function
function DisableButton(id)
{
var bButton = $("#" + id);
if (Page_ClientValidate())
{
$("#" + id).attr('disabled', 'disabled');
__doPostBack(id, '');
}
}
This works as expected in a non master page setup but when I try to use it with a page that has a master page, the postback occurs and the Page_Load fires but the button click handler never gets called. It's like the __doPostBack is not sending which control event to fire correctly.
Any suggestions for changes or even a whole different approach?
One idea for a different approach (disclaimer: this is not a fully baked solution) is to go from the submit action of the form instead of the click handler of the button.
The validation all happens through the submit handler of the form. If everything checks out, the form is allowed to submit. If you could hook into that process, then when the form started to submit for real, you could find all buttons with the class DisableOnSubmit and disable them.
Validation could take some time, however, and some people (annoyingly) seem to like to double-click on web forms, so it might be best to blend the approaches. Disable the button immediately with a click handler, then if validation fails, re-enable the buttons that were disabled.
EDIT In response to comments
This description could be turned to be more like the signature in the question (where any button could be made to be click-once regardless of its CSS classes).
Create a jQuery extender where the buttons that fit the selector are given an onClick handler and (if not already done) the hook is added to the validation being complete. The onClick handler adds the clicked button to a collection of "currently in click evaluation" buttons. If validation succeeds, the form submits normally. If validation fails, the buttons in the collection are re-enabled and removed from the collection.
For the evil update panels, you might want to look into specifying these events with live bindings (used to be a plugin, but I think it's now part of the jQuery core depending on which version you're using) so that the event handlers are reregistered when the partial postbacks complete.
I get the feeling you can use GetPostBackEventReference to do the actual postback once you've done your validation dance.
Edit Oops, forgot the other half of the answer :-)
As for the double postback, I've used Postback Ritalin by Dave Ward in the past to curtail those pesky hyperactive users.
Add this to your startup code (ready event handler):
var elemButton = $('#<%= Button1.ClientID %>');
var fnExistingHandler = elemButton[0].onclick;
elemButton[0].onclick = function()
{
fnExistingHandler();
if (!Page_BlockSubmit)
{
$(this)
.hide()
.after('<input type="button" value="Please Wait..." disabled="disabled" />');
}
};
Basically you append new code to existing click handler. Note checking global variable Page_BlockSubmit.
Instead of disabling submit button you can hide it and immediately insert disabled button in its place. Because this happens very quickly it will look as button becoming disabled to the user. Details are at the blog of Josh Stodola.
Edit: fixed client validation.
Haven't tried it but what about something like this:
$("input[type=submit]").live("click", function() {
$(this).hide().clone().insertAfter(this).show().attr("disabled", "disabled").val("Please wait...");
return true;
});
This will ensure a submit button isn't disabled which ASP.NET doesn't like.
I have a web service that validates some form data. The service is a ScriptService, and I am calling it from the client. I need to display a modal popup if the validation fails. If the user clicks "OK" on the modal popup, then I want to post back and save my data. "Cancel" should allow them to close the modal popup and let the user correct data, allowing one to resubmit. Currently, the modal popup displays every time regardless of the result of the validation.
I tried calling hide() and returning false, but neither worked.
I tried approaching this problem from a different perspective by assigning the TargetControlID property of the modalpopupextender to a hidden button and then calling show() on the modal popup if validation failed, but this did not cancel the postback. The modalpopup displays for approximately one second and the page posts back.
So you want to do something like:
function ValidateInput() {
MyScriptService.ValidateInput({however you are passing form data}, OnValidateComplete);
}
function OnValidateComplete(response) {
if ({response is bad}) {
$find('<%= ModalPopupExtender.ClientID %>').show();
}
}
You can then keep your TargetControlID, OnOkScript, etc. all the same. Perhaps with some code we can actually see what you are doing.
I have a few controls that inherit from ASP.NET buttons and use onserverclick.
If the user clicks twice, the button fires two server side events. How can I prevent this?
I tried setting this.disabled='true' after the click (in the onclick attribute) via javascript, but that blocks the first postback as well.
See this example for disabling control on postback. It should help you do what you're trying to achieve.
http://encosia.com/2007/04/17/disable-a-button-control-during-postback/
You don't necessarily want to show the button disabled on postback. You want to make sure they don't accidentally submit twice. So disabling or hiding the button as a result of a server-side action is already too late in the game. By this point the 2nd request is already on it's way. You need to either do it with javascript or make sure your server side code won't run twice.
In case of an updatepanel and a button inside a FormView-Template I use the following approach:
// Using that prm reference, hook _initializeRequest
Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(InitializeRequestBuchung);
// Abfangen von Mehrfachklicks auf Buttons für asynchrone Postbacks im Updatepanel
function InitializeRequestBuchung(sender, args) {
var arrButtonIds = ["ButtonInsert", "ButtonUpdate"];
// Get a reference to the PageRequestManager.
var prm = Sys.WebForms.PageRequestManager.getInstance();
if (prm.get_isInAsyncPostBack() & jQuery.inArray(args.get_postBackElement().id, arrButtonIds) > -1) {
args.set_cancel(true);
}
}
This cancels the following postback if an async postback is currently still active. Works perfectly.
Someone else said this somewhere on here a few days ago, and I concur - use javascript to simply hide the button instead of disabling it; you could show a "spinner" image in its place, which lets the user know what is going on.
Instead of hiding, what I have done is swapping buttons using javascript. Show another greyed out image on the click of the first button.
Set the Button property UseSubmitBehavior to false. Then create an OnClientClick function that disables the button.
It would look something like this:
<script type="text/javascript">
function disableFunctn(button){
button.disabled = true;
}
</script>
<asp:Button ID="button1" UseSubmitBehavior="false" OnClientClick="disableFunctn(this);"/>
fastest cheapest way:
<asp:Button ID="button1" UseSubmitBehavior="false" OnClientClick="this.disabled=true;"/>
You can also try for example btnSave.Enable = false; when the button is hit and before the processing for the button is done in the Click Event routine. If you need it to be reset to allow it to be enabled have a separate button that resets the button for reuse.
Another method is to set the button with verification so that the user is asked if they want to Save, it should pop up both times.
Yet another method would be to flag the first occurrence then set a popup for the second to verify a second or subsequent usage.