Here's the situation: I have a variable number of dynamically created update panels on my page, so I thought I would write one method which handles all of the loading for each one.
My Updatepanel creation looks something like this:
Dim newUpdp As New UpdatePanel
newUpdatep.ChildrenAsTriggers = False
newUpdatep.UpdateMode = UpdatePanelUpdateMode.Conditional
newUpdatep.ID = Guid.NewGuid.ToString
AddHandler newUpdatep.Load, AddressOf updatep_load_method
updatep_Holder.ContentTemplateContainer.Controls.Add(newUpdp)
updatep_Holder.Update()
This creates the update panel and binds its load event to the method "updatep_load_method". This method is called as soon as the Updatepanel is inserted into the holder. The method code is as follows:
Private Sub updp_load_method(sender As UpdatePanel, e As System.EventArgs)
Dim div As New HtmlGenericControl("div")
div.InnerText = Date.Time.Now.ToString
sender.ContentTemplateContainer.Controls.Add(div)
sender.Update()
End Sub
A little later on I want to update the panel, and refresh the time. So I use the javascript __doPostBack method. According to Dave Ward, the __doPostBack method follows the full page postback lifecycle, so I figured the load event of my Update panel would be fired and that "updatep_load_method" would be called by that particular update panel...
Although the partial postback occurs, and other update panel's load events are called, my bound ones aren't. So what's happening here?
You need to recreate dynamic controls during Page_Init and have to use the same Id (so you cannot do a Guid.NewGuid.ToString() while recreating the control).
Otherwise, ASP.Net will not be able to locate your control and populate it with data from ViewState.
Here's a good article that explains more about dynamic controls.
Try implementing the RaisePostBackEvent method in your code:
protected override void RaisePostBackEvent(IPostBackEventHandler source, string eventArgument)
{
//call the RaisePostBack event
base.RaisePostBackEvent(source, eventArgument);
//add whatever code you need to execute on postback here
}
Related
I have an MVC 5 view that acts as a parent view. Based on certain activities a user performs, I will load a partial view into the parent view. The partial view is loaded as part of a javascript function call. In my javascript call, I am loading my partial view with the content returned in the "data" variable below:
$.get(url, function (data) {
$('#id-ContainerForMainFormPartialView').html(data);
});
The data is written to an HTML div as follows:
<div class="container" id="id-ContainerForMainFormPartialView">
</div>
Immediately after the $.get call I run the following statement to disable a button that is part of the view that has been returned and written to the div:
$('#idAddLineItem').prop("disabled", true);
When the javascript function has completed the button is not disabled. Yet, I am able to disable the button using the same disable statement above using a button. I think that after the $.get invocation has written the partial view it is too soon to try and do something to any elements that are part of the partial view.
Is there an event I can hook into or something that will signal me when the time is right to try and do something to any of the elements of the partial view that has been loaded such as disabling a button which is what I am trying to do? Something like the javascript addEventListener() method that allows you to run code when certain events happen but in this case I need it to fire after a partial-view load is considered completely rendered and ready to use. An example would be greatly appreciated.
Thanks in advance.
Based on blex's statement the solution is as follows:
The correct way to disable a button that's part of a partial view being output:
// Correct Approach
$.get(url, function (data) {
$('#id-ContainerForMainFormPartialView').html(data);
$('#idAddLineItem').prop("disabled", true);
});
The incorrect way to disable a button that's part of a partial view being output:
//Incorrect Approach
$.get(url, function (data) {
$('#id-ContainerForMainFormPartialView').html(data);
});
$('#idAddLineItem').prop("disabled", true);
I originally had the disable statement outside the $.get call which allowed the code to run past it before the view was ready due to the asynchronous nature. Placing it inside the $.get allows it to not run until the partial view is done being output.
I'm using the ChromeWebDriver together with Selenium. The application is partically controlled automatically. Now I want the user to navigate to a page, where he has to choose a link from some list like
<ul>
<li>Google</li>
<li>Ecosia</li>
<li>Yahoo</li>
</ul>
I want to get the link automatically, where the user clicked on. As example, when he clicks on Google, I need some kind of event, that gave me http://google.de in C#. There exist a WebDriverEventListener, his ElementClicked event is exactly what I need:
private void EventDriver_ElementClicked(object sender, WebElementEventArgs e) {
if(e.Element.TagName == "a") {
string link = e.Element.GetAttribute("href");
MessageBox.Show($"User has clicked on link {link}");
}
}
But the big problem here: ElementClicked is only fired on clicks triggered by Selenium using C#. All events have this issue. For example, Navigated got fired after calling driver.Navigate().GoToUrl("http://stackoverflow.com"), but not after manually clicking on a link in the browser.
To solve this, I think its necessary to forward client-side JS events. Like this pseudocode:
$('a').click(function() {
SeleniumBackend.NotifyAboutClickEvent('a', $(this));
});
I know there is a method called ExecuteScript which allows to run JS in the browser. It seems possible to catch a direct return like
string jsReturnValue = driver.ExecuteScript("return 'test';");
For this case, that's not enough, since some sort of callback would be needed to be async.
object clickedLink = sharedWebDriver.ExecuteAsyncScript(#"
var callback = arguments[arguments.length - 1];
clickedLink('http://google.de');
");
That works, issue here: Only once. I can't bind an eventhandler, which notify me about later clicks...
It looks like you are creating the initial menu page. If that's true, you can just set a JS global variable using an onlick event and then use JavascriptExecutor to grab the variable setting and then use that to determine what link they clicked.
...or better yet, you can just detect the browser URL after they click and know where they went.
I only want to run a javascript method on the page load the 1st time only. If there is a postback I do not want to run that method again.
This method is setting the defaults to certain textboxes.
If I add an onLoad to the body element it runs it each time on the postback. I've tried a ClientScript.RegisterStartupScript but that too runs the method on the postback as well.
Am I going to have to do it old school where I have to increment a hidden value and check that each time?
Try defining the method within your Page_Load event using the IsPostBack property to determine if it is the initial load or not :
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
// It is the initial load, call your script
ClientScript.RegisterStartupScript(...);
}
}
The Page_Load event will be called every time that your page is loaded, regardless of a PostBack or not. It will only ever be false on the initial load, so if you place your call within there, it should only execute the script a single time.
I'm using Telerik UI for asp.net. Specifically I'm using RadTabStrip with partial page postbacks to allow the user to tab through different sets of data. When the user clicks a tab, some code executes and loads data just for that tab.
I've figured out how to execute codebehind: I set the OnTabClick property of the RadTabStrip, and then in codebehind I check what tab was clicked.
E.g.
protected void tab_Click(object sender, RadTabStripEventArgs e)
{
if (e.Tab.Text == "Info")
{
populateInfoTab();
}
}
private void populateInfotab()
{
// Do some stuff
}
However, I can't figure out how to execute client side javascript after a specific tab is clicked. What I tried:
Set OnClientTabSelected property, and then add some javascript:
function tab_ClientClick(sender, args)
{
var tab = args.get_tab();
if(tab.get_text() == "Info")
{
alert("Tab Clicked");
}
}
The problem is that I need to set the InnerHtml of some div in the clicked pageview after it is clicked. The div does not exist on page load (that specific RadPageView is hidden) so I cannot set it then. Once the user clicks into the tab, and after the page view loads, I need to be able to update the div's InnerHtml through JavaScript.
How would I go about doing this?
First option - if you do not set the RenderSelectedPageOnly property to true, all page views will be rendered on the initial load and you will be able to use JS to find/modify elements in them.
Second option - just set the content from the server as soon as you load the UC, this will usually make things simpler.
Third option - use client-side events (offered by the native PageRequestManager class or the RadAjaxManager, depending on how you setup your AJAX interactions) to execute when the response is received. The difficulty here is to determine which is the postback you need. Looking for the desired element and only executing logic if it exists is the simplest flag you can opt for.
Fourth option - register a script from the server code that will call your function, something like:
populateInfoTab();
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "someKey", "myDesiredFunction()", true);
where you may want to use the Sys.Application.Load to ensure it is executed later than IScriptControl initialization.
I am trying to fix some issues in an old asp.net application which uses ASP GridView. There are several events bound to the grid. Say sort, row click etc. I want to execute some js function after load/reload completes, (like after sort using header click etc.).
I tried
JQuery's ready function, which fires only on page load.
Placed a script block next to the grid
Placed a RegisterStartupScript in grid_sort (where DataBind happens)
none of them fires on grid reload after sort.
Server-side events always cause a full page lifecycle. But if there are UpdatePanels in the mix then you may get a partial page postback which won't trigger a page load event. Keep in mind the full page lifecycle happens regardless.
When you want to execute some client side code after handling some sort of server side event, you need a way to pass some information to the JS/jQuery after the page fully renders. Usually this is done by using 1 or more <asp:HiddenField> controls.
Typically I will set its ClientIDMode to static to make life easier on the JS side of things. So for example if you have this:
<asp:HiddenField ID="hfSomeData" runat="server" ClientIDMode="Static"
Value="Something set after handling some gridview event"
then you can do this on the javascript side to access the value:
$("#hfSomeData").val();
The following code will execute PostBackHandler based on either the jquery ready event or call from endRequest as issued by an UpdatePanel partial page update
// Handle Full Page postbacks
$(function () {
PostbackHandler(0);
});
// Handle Partial Page postbacks
// i.e. when Gridview embedded in an UpdatePanel
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function(sender, args){
PostbackHandler(1);
});
//PostBackType : 0 for Full Postback
// : 1 for Partial Postback
function PostbackHandler(PostBackType) {
var passed_in_data = $("#hfSomeData").val();
if (PostBackType === 0)
// do postback stuff
else
// do partial postback stuff
}