Hello all gurus in the area of ASP.NET AJAX and JavaScript!
Here's the deal: I have a user control (ascx) that currently contains a help Button and a ModalPopupExtender showing a Panel. The idea is that the user clicks the button and the help info is presented in a modal popup on top of the page, with another button to close it.
The help info can very well be larger than the window, so I have to resize the modal popup on show. When the control is coded as below, the Panel is resized initially, however; if the parent page has a validation error and is resent to the client, the javascript on top never executes.
Here's the control markup:
<script type="text/javascript">
// Adjust for popup y = 130 and a small gap.
var myAdjustedHeight = getPageHeight() - 150;
if (document.getElementById('<% =pnlPopUp.ClientID %>')) {
document.getElementById('<% =pnlPopUp.ClientID %>').style.height = myAdjustedHeight;
document.getElementById('<% =pnlScroll.ClientID %>').style.height = myAdjustedHeight - 20;
}
</script>
<asp:button id="btnHelp" runat="server" text="Help" />
<asp:updatepanel id="upPopUp" runat="server">
<contenttemplate>
<asp:panel id="pnlPopUp" runat="server" width="600">
<div class="header" style="float: left;">
Help
</div>
<asp:button id="btnClose" runat="server" text="Close" style="float: right; padding-bottom: 3px;" />
<asp:panel id="pnlScroll" runat="server" scrollbars="Vertical" style="clear: both;">
<asp:gridview id="grv" runat="server" autogeneratecolumns="true" showheader="false" gridlines="None" cellspacing="2" cellpadding="2">
</asp:gridview>
</asp:panel>
</asp:panel>
</contenttemplate>
</asp:updatepanel>
<ajaxtoolkit:modalpopupextender id="popUpExtender"
runat="server" backgroundcssclass="modalBackground" okcontrolid="btnClose"
targetcontrolid="btnHelp" popupcontrolid="pnlPopUp" x="100" y="130" />
(The GridView is filled with data in the Page_Load using a predefined DataSet in a basic fashion.)
I have tried to add this:
function pageLoad() {
document.getElementById('<% =popUpExtender.ClientID %>').add_shown(adjustHeight);
}
(where adjustHeight() is a function containing the code from the top) but when it fires I get null back for the ModalPopupExtender - and indeed it never seems to be included into the markup sent down the wire.
BTW, I need to add at least two instances of this help button to present help info for several elements on the page. Hence, I can't use the BehaviorID property of the ModalPopupExtender, since it is piped straight out to the page and I get an id collision.
So, how do I fix this? Am I to move the ModalPopupExtender to the Page or can I solve this within the ascx control?
If anyone has an idea on how to fix this, I would appreciate it.
Use this in your pageLoad:
$find('<% =popUpExtender.ClientID %>');
add_shown wouldn't exist for the HTML element, which document.getElementById returns.
Related
I have a problem, and looking for a solution for 2 days
Target : Create/edit client... in HTML build a dialog with and asp fields with clientIDMode static
<div id="divDialog" runat="server" clientidmode="Static" style="display: none;">
<div class="DialogFields">
<asp:Label ID="Label1" runat="server" Text="Firstname"></asp:Label>
<br />
<asp:TextBox ID="tbxFirstName" runat="server" ClientIDMode="Static"></asp:TextBox>
</div>
...
In script
$("#btnShowDialog").click(function () {
openDialog();
});
function openDialog() {
$("#divDialog").dialog('open');
$("#divDialog").parent().appendTo($("form:first"));
}
When I click the button btnShowDialog it works fine... But
Beneath it I have a gridview within it a edit button (asp:Linkbutton) with a event to the codebehind it looks like:
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="Edit" OnCommand="Edit_Click" CommandArgument='<%#Eval("RelationID") %>'
runat="server"><img src="../images/Edit-item.png" alt="Edit" /></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
In codebehind take the parameter from commandargument and fire LoadInfo (specific data to all the fields in de dialog).
LoadInfo(e.CommandArgument != null ? int.Parse(e.CommandArgument.ToString()) : -1);
but no way I get the dialog open.
I tried
ClientScript.RegisterStartupScript(this.GetType(), "Popup", "openDialog();", true);
and
ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "script", "openDialog();", true);
after this LoadInfo, push btnShowDialog button and it opens the dialog and all data perfect in place.
Also tried the other way around as Directly to Jquery function, get all data loaded and open the dialog. 2 problems, loading in codebehind was not even started before the dialog opens. and I only can get a static function in the codebehind.
A lot of ground to cover for me, but can any body help me out (even for a part).
...Thanx
If I understand your question correctly, you are trying to fire some client scripts (openDialog) from the server side, but they wont fire?
Try placing your page in an update panel, lets assume that we name the update panel "MyUpdatePanel". And then refer to the update panel like this:
ScriptManager.RegisterStartupScript(MyUpdatePanel, MyUpdatePanel.GetType(), "MyUpdatePanelScript", "openDialog();", true);
I believe a few friends and I have coded each other into a bit of a corner. Here's what's happening: We have an aspx page building a table of Entries using a repeater, and each row has its respective EntryID. Each row has a link to a modal that displays more detailed information, which we create on the fly with a div template and an eval('EntryID') on the repeater.
The problem now is we have a ContentTemplate we use with an UpdatePanel for a series of LinkButton presses the user can follow to alter the Entry. The issue is that we pass all of the information for the Modal details via a Javascript call that opens the modal, and I need to somehow get this information to the code behind for the LinkButton's onclick call.
<asp:UpdatePanel ID="StatusUpdatePanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Panel ID="pnlStatus" runat="server">
<asp:Panel ID="pnlStatusMain" runat="server">
<asp:Label ID="lblStatusText" runat="server" Text="Our validator returned a yellow status for this entry"></asp:Label>
<asp:LinkButton ID="lnkbtnChangeStatusToGreen" runat="server" OnClick="ChangeStatusToGreen_Click">Change status to green</asp:LinkButton>
<asp:Panel ID="pnlStatusConfirm" runat="server" CssClass="hideDiv">
Are you sure?<br />
<asp:LinkButton ID="lnkbtnCancelChangeStatus" runat="server" OnClick="CancelChangeStatus_Click" CssClass="grayText">Cancel</asp:LinkButton>
|
<asp:LinkButton ID="lnkbtnProceedChangeStatus" runat="server" OnClick="ProceedChangeStatus_Click" CommandArgument="">Yes, proceed</asp:LinkButton>
</asp:Panel>
</asp:Panel>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
The link in question being lnkbtnProceedChangeStatus.
The rest of the modal is template divs and tables that we use the Javascript call to populate with the appropriate information using html inserts. I'm thinking some sort of post back, but am not sure what would be the best way to go about it. Any ideas?
I have an UpdatePanel with a TabContainer in it. Each TabPanel has a Gridview in it (code not included since it's not important), and I would like to have a different UpdateProgress controls located in each TabPanel. Please see my code below for an example of what I'm trying to do.
I know the standard approach is to locate the UpdateProgress control outside of the UpdatePanel, but I would like it/them to be located inside the UpdatePanel and TabContainer because I want the "Loading..." message to appear right on top of each of my GridViews. Currently the UpdateProgress control works on the first TabPanel (as indicated below in my code), but not on the second or any subsequent TabPanels.
<asp:UpdatePanel ID="updTest" runat="server">
<ContentTemplate>
<ajax:TabContainer ID="conTest" runat="server">
<ajax:TabPanel ID="pnlTest1" runat="server">
<!--This UpdateProgress Control Does work-->
<asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="updTest">
<ProgressTemplate>
Loading, please wait....
</ProgressTemplate>
</asp:UpdateProgress>
</ajax:TabPanel>
<ajax:TabPanel ID="pnlTest1" runat="server">
<!--This UpdateProgress Control Doesn't work. How can I fix it?-->
<asp:UpdateProgress ID="UpdateProgress2" runat="server" AssociatedUpdatePanelID="updTest">
<ProgressTemplate>
Loading, please wait....
</ProgressTemplate>
</asp:UpdateProgress>
</ajax:TabPanel>
</ajax:TabContainer>
</ContentTemplate>
I'm open to another approach if the way I'm trying to accomplish this isn't the best way. Thanks for any ideas.
What you can do is still only have one updateprogress but inside of your put an updatepanel to change what your updateProgress shows.
something like this
<asp:UpdateProgress ID="UpdateProgress1" runat="server" DynamicLayout="true">
<ProgressTemplate>
<asp:UpdatePanel ID="up1" runat="server" >
<ContentTemplate>
<!-- put a label of something in here -->
</ContentTemplate>
</asp:UpdatePanel>
</ProgressTemplate>
</asp:UpdateProgress>
hopefully this makes sense, I'm not the best at explaining sometimes.
This control has a property Enabled that acts exactly as Visible behaves i.e. ?.Enabled = false hides the control.
I need to be able to keep all the tabs visible but some to be disabled under code control.
Any hints as to how I can achieve this? Thanks.
Try to set Enabled property for TabPanel.
<ajaxToolkit:TabContainer
ID="TabContainer1" runat="server" ActiveTabIndex="0">
<ajaxToolkit:TabPanel ID="TabPanel1" runat="server" HeaderText="TabPanel1"></ajaxToolkit:TabPanel>
<ajaxToolkit:TabPanel ID="TabPanel2" runat="server" HeaderText="TabPanel2"></ajaxToolkit:TabPanel>
<ajaxToolkit:TabPanel ID="TabPanel3" Enabled="False" runat="server" HeaderText="TabPanel3"></ajaxToolkit:TabPanel>
</ajaxToolkit:TabContainer>
Or in code-behind,
TabContainer1.Tabs[0].Enabled = false;
Here is one possible solution using client-side scripting. Basically, handle the OnClientActiveTabChanged event for the TabContainer (which fires whenever the active tab is changed). Then, if the tab is one that you don't want the user to use, change the ActiveTabIndex property of the TabContainer back to one that is acceptable.
Tab Container:
<asp:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="1"
Height="126px" Width="400px" ClientIDMode="Predictable"
onclientactivetabchanged="tabClickCheck" >
<asp:TabPanel ID="TabPanel1" runat="server" HeaderText="TabPanel1">
</asp:TabPanel>
<asp:TabPanel ID="TabPanel2" runat="server" HeaderText="TabPanel2">
</asp:TabPanel>
<asp:TabPanel ID="TabPanel3" runat="server" HeaderText="TabPanel3">
</asp:TabPanel>
</asp:TabContainer>
Javascript handler:
<script type="text/javascript">
function tabClickCheck() {
var tabCont = document.getElementById("<%=TabContainer1.ClientID %>").control;
var tabInd = tabCont.get_activeTabIndex();
tabCont.set_activeTabIndex(2);
}
</script>
This function just sets the ActiveTabIndex to 2, regardless of which tab you clicked (you'll notice I'm also getting the current ActiveTabIndex, but I don't do anything with it - that's just to show you how). Obviously, use whatever logic makes sense for your app =)
Old hand at ASP.NET, new to the UpdatePanel. I have a reporting page which executes a fairly length SQL query... takes about 10 seconds right now. What I would like to do is have my page fully render, with some placeholder text (Loading...) and then have the UpdatePanel kick off the actual time-consuming reporting process and render the report when it's done.
So... my theory is to use RegisterStartupScript() to kick this off and drop the string from GetPostBackEventReference() to trigger the UpdatePanel update. Some problems crop up:
1) Can I actually use GetPostBackEventReference w/ the UpdatePanel or do I need to trigger it some other way? Use this method on a button inside the Update Panel?
2) What event gets triggered when the postback reference is the UpdatePanel? It's not clear to me. I've got to call my databinding code somewhere! Again, maybe I need to use a button inside?
I had to do something very similar recently, here's how i did it (right or wrong):
The trick is a "Hidden Async Postback Trigger".
<asp:UpdatePanel ID="upFacebookImage" runat="server">
<ContentTemplate>
<!-- Your updatepanel content -->
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="hiddenAsyncTrigger" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<asp:Button ID="hiddenAsyncTrigger" runat="server" Text="AsyncUpdate" style="display:none;" />
Then from JavaScript, whenever you want to trigger the async postback, you do this:
__doPostBack('<%= hiddenAsyncTrigger.ClientID %>', 'OnClick');
In my example, i needed to trigger an async postback from a particular JS event. But you could attach it to doc ready.
I seem to remember trying #Marko Ivanovski's way, but for some reason it didn't work. I think you need to specify a "postback-able" control (ie a button) to trigger the postback.
HTH.
Updating this with my solution, I pieced together mostly from the first answer above.
I need my page to load, then then start loading content for my update panel. The panel calls some webservices and we don't want the whole page to crash in the event that the remote server doesn't respond. We don't want the wait either.
My HTML:
<asp:UpdatePanel ID="udpCheckout" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:Image ID="imgSpinner" runat="server" Visible="true" ImageUrl="~/images/ajax-loader.gif" />
<br />
<asp:Label ID="lblWait" runat="server" Visible="true" Text="Please wait..."></asp:Label>
<asp:Button ID="hiddenAsyncTrigger" runat="server" Text="AsyncUpdate" style="display:none;" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="hiddenAsyncTrigger" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
My Code behind snippets:
In page_load:
ScriptManager.RegisterStartupScript(Me.Page, Me.Page.GetType, "LoadUpdate", GetPostBackEventReference(hiddenAsyncTrigger, String.Empty), True)
And the button handler:
Sub LoadUpdatePanels(ByVal o As Object, ByVal e As EventArgs) Handles hiddenAsyncTrigger.Click
System.Threading.Thread.Sleep(5000) 'wait 5 seconds so I can see the page change
imgSpinner.Visible = False
lblWait.Text = "Content is now loaded."
'udpCheckout.Update()
End Sub
This was my test to see if I could get it working. Now to replace all of this with the real code!
Try something like this (not tested).
Set the UpdateMode of the UpdatePanel to Conditional.
Add this to your <head> section:
<script type="text/javascript">
window.onload = __doPostBack('UpdatePanel1', ''); // Replace UpdatePanel1 with the ID of your UpdatePanel
</script>
Simplifying RPM1984's very helpful earlier answer (thanks ;)) and showing some tweaks & a little more of the surrounding detail that I found necessary:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="upFacebookImage" runat="server">
<ContentTemplate>
<asp:PlaceHolder runat="server" ID="PlaceHolderMediaPrompts" />
<asp:Button ID="hiddenAsyncTrigger" runat="server" Text="AsyncUpdate" OnClick="WasPage_Load" style="display:none;" />
</ContentTemplate>
</asp:UpdatePanel>
Note:
The hidden button's vital OnClick= parameter, this is what specifies the server function to call!
No trigger clause or triggers in the Update-panel, I am using the child controls which are automatically triggers - specifically the button Click event.
And to trigger it from client-side Javascript you can use:
document.getElementById("hiddenAsyncTrigger").click();
However, I found it necessary to prevent this being called on subsequent page loads (as it caused unnecessary page load looping & consequent flicker). See the neat little IsPostBack() check below :)
e.g. To invoke this after page load (as per the original question), I just added a call to invoke the above line of code as the onload-parameter to the main Body-tag thus:
<body onload="DoPostLoad();">
...
<script type="text/javascript">
function DoPostLoad()
{
if ( IsPostBack() != true ) // ***This is NEW and ESSENTIAL! ***
document.getElementById("hiddenAsyncTrigger").click();
}
function IsPostBack() { // Ref. https://stackoverflow.com/questions/26978112/execute-javascript-only-on-page-load-not-postback-sharepoint
var ret = '<%= Page.IsPostBack%>' == 'True';
return ret;
}
. . .
</script>
</body>