So I want to run some javaScript function after my updatepanel is updated, so I have:
function pageLoad() {
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(panelLoaded);
}
function panelLoaded(sender, args) {
alert("foobar");
}
With the above code, if I update the panel one time, "foobar" will be alerted one time; If I update the panel the second time, "foobar" will pop up twice; the third time I trigger the panel to update, "foobar" popped up three times... 4th time pop 4 times so on and so forth....
What caused this??
Thanks~~~
This is because pageLoad is executed during updatepanel postbacks as well. There is an easy solution:
function pageLoad(sender, eventArgs) {
// If this is being executed by ajax
if (eventArgs) {
// And this is only a partial load
if (eventArgs.get_isPartialLoad()) {
// Don't perform any further processing
return;
}
}
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(panelLoaded);
}
Thanks all, problem seem to be having too many prm instances as Sam mentioned. I added Sys.WebForms.PageRequestManager.getInstance().remove_pageLoaded(panelLoaded); after the alert() and everything is good.
This is what is happening. pageLoad basically functions as a combination of Application.Init and PageRequestManager.EndRequest. That means it works on Application Initialization ( approximately DOM Ready ) and on each Partial PostBack
So pageLoad works on all PostBacks; full and partial.
Now you are binding up pageLoaded event again on the ScriptManager's instance on every partial postback again and again causing this behaviour.
Related
I need to get the id of the panel that is about to start a postback, so I have a generic way to block ui on this panel.
So far I have this function:
function BeginRequestHandler(sender, args) {
$('#' + args.get_updatePanelsToUpdate()[0]).block({ message: null });
}
attached like this:
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler);
this works pretty well to get the id if control that causes partial postback is inside update panel, but if it is outside (using a trigger), args.get_updatePanelsToUpdate() is always null
I've seen this answer, but it wont work forme because function is fired after partial postback is complete, I need it before..
Thank you
So here's what I did:
created 2 functions to block (on partial postback begin) and unblock (on partial postback end):
function BeginRequestHandler(sender, args) {
$('#' +sender._postBackSettings.panelsToUpdate[0].ReplaceAll('$', '_')).block({ message: 'loading...' });
}
function EndRequestHandler(sender, args) {
$('#' + sender._postBackSettings.panelsToUpdate[0].ReplaceAll('$', '_')).unblock();
}
Registered above functions on my page right after my script manager:
<script type="text/javascript">
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler);
</script>
Some conditions:
I'm using jquery UI block plugin but you should use what better fits your needs.
You update panels should have ClientIDMode="AutoID" if your using .NET 4.0 +
I used the following helper function cause js doesn't make a real replace all and to deal with asp net autoID's:
String.prototype.ReplaceAll = function (stringToFind, stringToReplace) {
var temp = this;
var index = temp.indexOf(stringToFind);
while (index != -1) {
temp = temp.replace(stringToFind, stringToReplace);
index = temp.indexOf(stringToFind);
}
return temp;
}
If you just want to disable (or animate in some other way) the UpdatePanel, why not just use UpdatePanelAnimation? It provides you with the following hooks (not sure if that's the right word):
OnUpdating - Generic animation played as when any UpdatePanel begins
updating
OnUpdated - Generic animation played after the UpdatePanel
has finished updating (but only if the UpdatePanel was changed)
I have an UpdatePanel with a repeater in it that is re-bound after a user adds an item to it via a modal popup.
When they click the button to add a new row to the repeater the code-behind looks something like this:
protected void lbtnAddOption_Click(object sender, EventArgs e)
{
SelectedOption = new Option()
{
Account = txtAddOptionAccountNumber.Text,
Margin = chkAddOptionMargin.Checked,
Symbol = txtAddOptionSymbol.Text,
Usymbol = txtAddOptionUsymbol.Text,
};
Presenter.OnAddOption(); // Insert the new item
RefreshOptions(); // Pull down and re-bind all the items
mpeAddOptionDialog.Hide(); // Hide the modal
// ... Make call to jQuery scrollTo() method here?
}
This works fine and the new row will show up quickly via the UpdatePanel.
However, there are often hundreds of rows and where the new one is added is based on the current sorting column used.
So, I wanted to take this as a chance to use the sweet jQuery ScrollTo plugin. I know that if I give it the ID of my overflowed container div and the ID of an element within it, it will smoothly scroll straight to the users newly added row.
However, there are two problems:
I need to find the appropriate row so I can snag the ClientID for it.
I need to execute the jQuery snippet from my code-behind that will cause my newly updated repeater to scroll to the right row.
I've solved #1. I have a reliable method that will produce the newly added row's ClientID.
However, problem #2 is proving to be tricky. I know I can just call ScriptManager.RegisterStartupScript() form my code-behind and it will execute the JavaScript on my page.
The problem I'm having is that it seems that it is executing that piece of JavaScript before (I'm guessing) the newly refreshed DOM elements have fully loaded. So, even though I am passing in the appropriate jQuery line to scroll to the element I want, it is erroring out for me because it can't find that element yet.
Here is the line I'm using at the end of the method I posted above:
string clientID = getClientIdOfNewRow();
ScriptManager.RegisterStartupScript(this, typeof(Page), "ScrollScript", String.Format("$(\"#optionContainer\").scrollTo(\"{0}\", 800);", clientID), true);
What do I need to do so I can ensure that this line of JavaScript isn't called until the page with the UpdatePanel is truly ready?
If the stuff you need to process is in the update panel, then you need to run your JS once that panel is loaded. I use add_endRequest for that. This below is hacked from something rather more complex. It runs once on document ready, but installs the "end ajax" handler which is triggered every time your update panel is updated. And by the time it fires, it's all there for you.
var prm = Sys.WebForms.PageRequestManager.getInstance();
jQuery(document).ready(function () {
prm.add_endRequest(EndRequestHandler);
});
function EndRequestHandler(sender, args) {
// do whatever you need to do with the stuff in the update panel.
}
Obviously you can inject that from code-behind if you want.
You can use the Sys.Application.load event which is raised after all scripts have been loaded and the objects in the application have been created and initialized.
So your code would be:
string clientID = getClientIdOfNewRow();
ScriptManager.RegisterStartupScript(this, typeof(Page)
,"ScrollScript"
,String.Format("Sys.Application.add_load(function(){{$(\"#optionContainer\").scrollTo(\"{0}\", 800);}});"
, clientID)
, true);
I've seen in quite a few examples of asp.net ajax client side script the following:
function fHelloWorld(source, eventArgs)
{
}
If I run an alert on the source it's returned as an object. Can I use this to access what called the function? And if so how? i've tried things like
source.id;
Without luck
The best advice that I can offer is, given an object, enumerate over the properties and write them out, including their values to the page. Then inspect the property values and will surely find out if such a property exists. You could also use Firebug, Fiddler2 or host of other tools to inspect the object.
Here's an example
function pageLoad(sender, args) {
// add function to the PageRequestManager to be executed on async postback initialize
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
}
function InitializeRequest(sender, args) {
// Display loader gif when async postback initialized by element_in_question
if(args._postBackElement.id === 'id_of_element_in_question' {
$get('ajax-loader').style.display = 'inline';
}
}
Run the page with Firefox & Firebug, set a breakpoint inside your function, and inspect the source object interactively.
You can also display the object with console.log to get an object inspection hyperlink:
function fHelloWorld(source, eventArgs)
{
console.log("%o", source);
}
Is there a way to execute script when an UpdatePanel process is finished.
I have a page that allows "inserting", "copying", and "editing" of a record.
This is all done on an UpdatePanel to prevent a page navigation.
Somewhere else on the page I would like to print a "flash" message - like "You have successfully entered a record." It is not near the UpdatePanel and I'd like to use a jQuery effect on the message so it fades out after 4 seconds. How can I send script back with the UpdatePanel or have it execute after a UpdatePanel refresh? Should I write script to an asp:literal? thoughts?
Yes:
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequestHandler);
And then:
function endRequestHandler(sender, args)
{
// Do stuff
}
Documentation here and here. Keep in mind that this will fire for every AJAX request on the page.
This should do the trick:
<script type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(BeginRequestHandler);
prm.add_endRequest(EndRequestHandler);
function BeginRequestHandler(sender, args)
{
//Jquery Call
}
function EndRequestHandler(sender, args)
{
//Jquery Call
}
</script>
Here is an article for how to do it using ScriptManager's static method RegisterClientScriptBlock. Tried it and works like a charm.
http://csharperimage.jeremylikness.com/2009/06/inject-dynamic-javascript-into-aspnet.html
var requestManager = Sys.WebForms.PageRequestManager.getInstance();
requestManager.add_beginRequest(function () { alert('here1') });
requestManager.add_endRequest(function () { alert(here2') });
Source: http://www.howtositecore.com/?p=36
The Sys.WebForms.PageRequestManager.getInstance() method works great for me as well.
I work with a lot of pages that contain multiple Updatepanels and I've learned that this will automatically fire even if the Updatepanel you don't want it for refreshes. So inside the function that fires on the event make sure you have something like:
function BeginRequestHandler(sender, args) {
if (args.get_postBackElement().id == "ID of the Updatepanel") {
// do stuff here
Bruno,
First, to answer your direct question. In your callback that is being called by the update panel, you should be able to use a RegisterStartupScript call to invoke a JS method . Then in your JS method, you would show the message and then you can use do a:
setTimeout('$('#myMessage').fadeOut("slow")', 4000);
to have it fade away after 4 seconds.
To go one step further, since you're already implementing JavaScript, I would invite you to check out this article about UpdatePanels. If possible, I would try to send Ajax calls to do your inserting, copying, and editing and this would further simplify your user feedback and would prevent excess info across the wire.
I'm looking for something like OnClientClick for a button, but I want it to happen after the postback (instead of before). I'm currently using the following, which works, but it adds the script block over and over again, which is not what I want. I simply want to execute an existing client script function.
ScriptManager.RegisterClientScriptBlock(
this,
typeof( MyList ),
"blah",
"DraggifyLists();",
true );
If you're using ASP.NET AJAX, you could try the following:
addRequestHandler() must be called when your page loads
function addRequestHandler()
{
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequestHandler);
}
function endRequestHandler(sender, args)
{
// This function will be called after the postback has completed
// add your JavaScript function call here
}
This is based on code from Disturbed Budda