UI dialog problem with scriptManger and updatePanel - asp.net

i call my UI dialog from page which has scriptManager, this way:
function openDialog() {
var $dialog = jQuery('#dialog');
$dialog.load('dialog.aspx');
$dialog.dialog({
autoOpen: false,
title: 'Add New Contact Personel',
modal: true,
height: 200,
width: 400,
show: 'puff',
hide: 'puff',
close: function (event, ui) {
$dialog.html('');
$dialog.dialog('destroy');
}
});
$dialog.dialog('open');
}
body of dialog.aspx looks like this:
<body>
<form id="form1" runat="server">
<%-- <asp:ScriptManagerProxy ID="proxyScriptor" runat="server"></asp:ScriptManagerProxy>
<asp:UpdatePanel ID="upadatePanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>--%>
<div>
<table border="0">
<tr>
<th>SomeText:</th>
<th><asp:TextBox ID="someTextBox" runat="server"></asp:TextBox></th>
</tr>
</table>
</div>
<asp:Panel ID="updatePanel" runat="server">
<asp:Button ID="UpdateLoger" runat="server" Text="Update" onclick="Update_Click" />
</asp:Panel>
<%-- </ContentTemplate>
</asp:UpdatePanel>--%>
</form>
</body>
now: if i click updateBtn i want to update text in postback, close UI dialog and do refresh like this:
UpdateText(someTextBox.Text);
string script = #"jQuery('#dialog').html('');jQuery('#dialog').dialog('destroy');window.location.reload()";
ScriptManager.RegisterClientScriptBlock(this, typeof(UpdatePanel), "jscript", script, true);
so if add another script manager on this page for UI dialog, very very wird things have happend (like __doPostBack doesn't work), if i remove scriptManager, updatePanel doesnt show it contents, if i put scriptMangerProxy , updatePanel doesn't show it contents either. So how i should do it?

You've got a lot going on here. One problem you're running into is that you're treating dialog.aspx like it's loading into it's own window or iframe. In reality, its just being inserted as a document fragment into the page's DOM. I suspect if you inspect the source, you'll find multiple <body> tags.
There's several ways of doing this. My dialogs are typically unique to a particular page, so I'll handle the dialog somewhat like this:
Page.aspx
<html>
<head>...</head>
<body>
<!-- page content -->
<asp:Button ID="btnOpenDialog" runat="server" OnClick="btnOpenDialogClick" Text="Open Dialog" />
<asp:UpdatePanel ID="upDialogs" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Panel ID="pnlDialog" runat="server" CssClass="pnlDialog" Visible="false">
<!-- Dialog form -->
<asp:Button ID="btnSubmit" runat="server" OnClick="btnSubmitClick" Text="Submit" />
</asp:Panel>
</ContentTemplate>
<Triggers>
<asp:AsyncPostbackTrigger ControlID="btnOpenDialog" />
</Triggers>
</asp:UpdatePanel>
<script>
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function() {
$("div.pnlDialog").dialog({
autoOpen: true,
title: 'Add New Contact Personel',
modal: true,
height: 200,
width: 400,
show: 'puff',
hide: 'puff',
close: function (event, ui) {
$dialog.html('');
$dialog.dialog('destroy');
}
});
}
</script>
</body>
</html>
Page.aspx.cs
...
protected void btnOpenDialogClick(object sender, EventArgs e)
{
pnlDialog.Visible = true;
upDialogs.Update();
}
protected void btnSubmitClick(object sender, EventArgs e)
{
... save values ...
pnlDialog.Visible = false;
upDialogs.Update();
}
...
Basically, we register a JS function to fire every time the page performs an asynchronous postback. This functions looks for the dialog box code. If it finds it, it wires it up with jQueryUI. If it doesn't find anything, it just finishes silently. If you have multiple dialogs on the page, this can easily be refactored to flexibly handle them.

Related

ASP.NET - lazy loading dynamic tabs

I'm stumped on this one and hope someone out there's done something similar.
I have an ASP.NET application that has a number of AJAX toolkit tabs. The number of tabs varies page to page, since they're dynamically generated based on settings in a config file.
That being said, some of the tabs are database-driven. The load time when a number of these tabs are on the page can be significant, so I want to implement lazy loading.
I'm following Matt Berseth's pattern, but it seems to break down when the number of tabs is dynamic (each tab needs its own method on the page).
If anyone has a suggestion on how to tackle this, it'd be much appreciated.
I've started working with a small app to get the lazy loading to work. This lazy loads the second tab (which is hard coded), but the third tab is what I'm struggling with (it's dynamically added).
Edited to add code: ASPX page
<script language="javascript" type="text/javascript">
function clientActiveTabChanged(sender, args) {
// see if the table elements for the grids exist yet
var isTab2Loaded = $get('<%= this.lbl2.ClientID %>');
// if the tab does not exist and it is the active tab,
// trigger the async-postback
if (!isTab2Loaded && sender.get_activeTabIndex() == 1) {
// load tab1
__doPostBack('btnTrigger', '');
}
// else if (!isTab2Loaded && sender.get_activeTabIndex() == 2)
// load tab2
// __doPostBack('btnEmployeesTrigger', '');
}
</script>
<asp:scriptmanager ID="Scriptmanager1" runat="server"></asp:scriptmanager>
<div>
<cc1:TabContainer ID="tc1" runat="server" OnClientActiveTabChanged="clientActiveTabChanged">
<cc1:TabPanel TabIndex="0" runat="server" HeaderText="Tab1" ID="Tab1">
<ContentTemplate>
<asp:UpdatePanel ID="up1" runat="server">
<ContentTemplate>
<asp:Label ID="lbl1" text="I am here" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</ContentTemplate>
</cc1:TabPanel>
<cc1:TabPanel runat="server" HeaderText="Tab2" ID="Tab2">
<ContentTemplate>
<asp:UpdatePanel ID="up2" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:Label ID="lbl2" Text="Load when called" Visible="false" runat="server" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnTrigger" />
</Triggers>
</asp:UpdatePanel>
</ContentTemplate>
</cc1:TabPanel>
</cc1:TabContainer>
</div>
<input ID="btnTrigger" style="display:none;" runat="server" type="button" onserverclick="btnTrigger_Click" />
<input id="btnTrigger2" style="display:none;" runat="server" type="button" onserverclick="btnTrigger2_Click" />
Codebehind:
protected void Page_Init(object sender, EventArgs e)
{
//TabPanel tp = new TabPanel();
//tp.Controls.Add(new LiteralControl("Load first"));
//tp.HeaderText = "Tab1";
//tc1.Tabs.Add(tp);
//tc1.ActiveTabIndex = 0;
//TabPanel tp2 = new TabPanel();
//UpdatePanel up1 = new UpdatePanel();
//up1.Controls.Add(new LiteralControl("Load me when called"));
////up1.Triggers.Add(new AsyncPostBackTrigger());
//AsyncPostBackTrigger trg = new AsyncPostBackTrigger();
//tp2.Controls.Add(up1);
//tp2.Controls.Add(new LiteralControl("Load when called"));
//tp2.HeaderText = "Tab2";
//tc1.Tabs.Add(tp2);
TabPanel tp3 = new TabPanel();
tp3.HeaderText = "Tab3";
UpdatePanel up3 = new UpdatePanel();
LiteralControl lc = new LiteralControl("Load me when needed");
lc.ID = "lit3";
lc.Visible = false;
up3.ContentTemplateContainer.Controls.Add(lc);
tp3.Controls.Add(up3);
tc1.Controls.Add(tp3);
}
protected void btnTrigger_Click(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(2500);
this.lbl2.Visible = true;
}
Is the content of the Tabs also database-driven like a CMS?
You could use UserControls as Content and let all implement the same interface f.e. IDataBindable with a function BindData. On this way you can lazyload these UserControl independently of its content.
On ActiveTabChanged you only have to call this function and thenUpdate on the TabContainer's UpdatePanel.
The quick way to do this might be to not load any tabs (i.e. don't actually give them any content) besides the default until that tab is clicked (detected during OnActiveTabChanged or OnClientActiveTabChanged).
However, Tim's method allows the OnActiveTabChanged method to be as simple as databinding the UserControl relative to that tab - that's probably the best method, though it is more effort.

How to display value in the SimpleModal's dialog?

my question is really simple. I have a asp.net button. I can use it to call the simpleModal and have a dialog displayed. Now, I added a label control in the dialog, and would like this label to display some value. What should I do?
Here is my codes
$('#<%= btnOpen.ClientID %>').click(function(e) {
e.preventDefault();
$('#content').modal({
onOpen: function(dialog) {
dialog.overlay.fadeIn('slow', function() {
dialog.data.hide();
dialog.container.fadeIn('slow', function() {
dialog.data.slideDown('slow');
});
});
},
onClose: function(dialog) {
dialog.data.fadeOut('slow', function() {
dialog.container.slideUp('slow', function() {
dialog.overlay.fadeOut('slow', function() {
$.modal.close(); // must call this!
});
});
});
}
});
e.preventDefault();
// return false;
});
<asp:Button ID="btnOpen" runat="server" Text="ASP.NET Open"/>
<div id="content" style="display: none;">
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
</div>
I assume since you said that your question is simple that you just have an unfamiliarity with jQuery. You can put this in your click function, or in the $(document).ready function, depending on your full requirements:
var yourValue = ; // put your function or value here
$('#Label1').text(yourValue);
Note: You'll need to use .html instead of .text if you have a string with tags, but .text is faster.
Lol, I am answering my own question again, but I will give credit to mNVhr tho.
I finally get the whole thing work. The trick for asp.net button to fire a postback, along with javascript's postback, is to put the asp.net button into an update panel. Here is the code I have
For the javascript part:
<script src="js/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="js/jquery.simplemodal-1.3.5.js" type="text/javascript"></script>
<script type="text/javascript">
function myOpen() {
$('#content').modal({
onOpen: function(dialog) {
dialog.overlay.fadeIn('slow', function() {
dialog.data.hide();
dialog.container.fadeIn('slow', function() {
dialog.data.slideDown('slow');
});
});
},
onClose: function(dialog) {
dialog.data.fadeOut('slow', function() {
dialog.container.slideUp('slow', function() {
dialog.overlay.fadeOut('slow', function() {
$.modal.close();
});
});
});
}
});
}
function myClose() {
$.modal.close();
}
</script>
For the HTML markup
<asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Button ID="btnOpen" runat="server" Text="Open" OnClick="btnOpen_Click" OnClientClick="myOpen();" />
</ContentTemplate>
</asp:UpdatePanel>
<div id='content' style="display: none">
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="btnSave" runat="server" Text="Save" OnClick="btnSave_Click" />
<input id="Button2" type="button" value="Close" onclick="myClose();" />
<asp:Label ID="Label2" runat="server" Text=""></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
</div>
For the code behind:
protected void Page_Load(object sender, EventArgs e)
{
}
private void CloseDialog()
{
string script = string.Format(#"myClose()");
ScriptManager.RegisterClientScriptBlock(this, typeof(Page), UniqueID, script, true);
}
protected void btnSave_Click(object sender, EventArgs e)
{
if (TextBox1.Text == "1")
CloseDialog();
else
Label2.Text = TextBox1.Text;
}
protected void btnOpen_Click(object sender, EventArgs e)
{
TextBox1.Text = DateTime.Now.ToString();
UpdatePanel1.Update();
}
I hope this tiny code can help those asp.net developer who want to use the nice jQuery in their projects.
As you can see, from the above codes.
When I click on the btnOpen button, two postbacks fired. One is from the asp.net code behind, which assign current datetime to the textbox control inside the modal dialog. The second postback is from the javascript, which open the modal dialog. The asp.net button has to be inside the update panel. Otherwise, the modal dialog will only stay for about 0.5 second.
When I click on the btnSave inside the modal dialog. Postback also occurred. I have a little logic here. When the textbox's value is 1, I call the closeDialog() function. When the value is other numbers, the modal dialog stay opening, and the label control inside the dialog will display the number from the text box.
jQuery is nice, but as a .Net developer, it is just new, and sometimes difficult for me to understand it, especially for the conflict of postbacks between javascript and .net.
I hope this answer is helpful.

JQuery BlockUI with UpdatePanel Viewstate Issue

I have an update panel within a div that I modal using the JQuery plugin BlockUI. Inside the UpdatePanel is a textbox and a button. When I enter something in the textbox and click the button I am unable to retrieve the text in the textbox. When I debug it shows the textbox having no value.
<asp:UpdatePanel ID="upTest" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<div id="divTest">
<asp:TextBox ID="txtTestVS" runat="server" /><br />
<asp:Button ID="cmdTest" Text="TEST" OnClick="cmdTest_Click" UseSubmitBehavior="false" runat="server" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
SERVER-SIDE:
protected void cmdTest_Click(object sender, EventArgs e)
{
string x = txtTestVS.Text;
}
This should clarify things. Here are the total contents of the page.
SHOW MODAL
<div id="divTest">
<asp:UpdatePanel ID="upTest" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:TextBox ID="txtTestVS" runat="server" /><br />
<asp:Button ID="cmdTest" Text="TEST" OnClick="cmdTest_Click" UseSubmitBehavior="false" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
This is a common problem with dialog plug-ins. The problem is when content is put in the blockUI container, it's appended to the element, and no longer in the form being submitted to the server. To solve this you need to edit the blockUI code a bit:
Here's the source: http://github.com/malsup/blockui/blob/master/jquery.blockUI.js
Change this:
Line 262:
var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
to:
var layers = [lyr1,lyr2,lyr3], $par = full ? $('form') : $(el);
and this:
Line 382:
els = $('body').children().filter('.blockUI').add('body > .blockUI');
to:
els = $('form').children().filter('.blockUI').add('form > .blockUI');
That should get you going and the textbox values coming through.
(Response courtesy of Nick Craver https://stackoverflow.com/users/13249/nick-craver)
If you are trying to use blockUI on a button within an update panel (i.e. you click the button within the update panel and the UI gets blocked), you need to handle it using PageRequestManager events
prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(function() {
$.blockUI({ message: '<img src="../../Content/images/Busy2.gif" />' });
});
prm.add_endRequest(function() {
$.unblockUI();
});
Or on a button click, if you want to display a modal window with this text box and a button, you can try something like this

ASP.NET 3.5: Display UpdateProgress during Page_Load()

I am building an ASP.NET site using Visual Studio 2008 and have a page looking like this (stuff snipped)
<asp:Content ID="Content2" ContentPlaceHolderID="PageContentPlaceHolder" runat="server">
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
the page here..
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="100">
<ProgressTemplate>
<div>
<asp:Image ID="AjaxImage" runat="server" ImageUrl="Ajax.gif" />
</div>
</ProgressTemplate>
</asp:UpdateProgress>
</asp:Content>
The page_load starts a long (>5s) process
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LongRunningProcess();
}
}
How can I display the UpdateProgress while the LongRunningProcess is running? It does work when I move the LongRunningProcess() call to a button onclick handler.
Move your page_load code into a new function.
Add a AJAX timer into the ContentTemplate section of your page. Set the interval to 500. (1/2 second)
Double-click on the Timer object in Design view to create a _tick handler.
In the _tick handler created in the previous step, call the following code
protected void My_Timer_Tick(object sender, EventArgs e)
{
My_Timer_Name.Enabled = false;
My_Page_Load_Function(); // Function created in step 1 above)
}
protected void My_Page_Load_Function()
{
System.Threading.Thread.Sleep(5000); // A delay to simulate doing something.
lblMyLabel.Text = "Done!"; // Write output to page.
}
Create a normal div that shows the Ajax.gif so it shows "processing" by default.
In the javascript pageLoad() function, make a call back to the page using Ajax's PageMethods.
function pageLoad(sender, args) {
PageMethods.getVersions(LoadVersionsCallback);
}
The method you are calling in your .aspx.cs file has to be static, it can take parameters and looks something like:
[System.Web.Services.WebMethod]
public static string getVersions()
{
StringBuilder sb = new StringBuilder();
... etc.
return sb.ToString();
}
The javascript function that you specified when you called the method will run when the method completes. It will be passed the results. At the end of this function you hide the Ajax.gif div.
function LoadVersionsCallback(result) {
// do something with the results - I load a dropdown list box.
...etc.
// here is where you hide your div holding the Ajax.gif
}
And then you work on making whatever it is you are doing run in less than 1 second....
I would put a Ajax timer on the page and set it for less than a second... It will only run once and after its first tick then you need to disable it otherwise it will fire again. (you don't want to start your long running process more than once...)
then on the OnTimerTick event I would start your long running process that way your page fully renders and you can display your UpdateProgress while its running.
you out to be able to move the code that you had for your button click to the time tick...
I used JBrooks idea above (i.e. showing the progress indicator as part of a Panel that also includes the Iframe, so that it shows even before the Iframe first loads), but simplified it: style the iframe so that when it does appear it is on top of the animated GIF.
Requires no Javascript or C# code-behind.
Here's the relevant ASPX, followed by the CSS. You'll have to noodle with the "top" setting in the style to cover the image you use.
<asp:Panel ID="DetailPanel" runat="server" CssClass="submitBox detailPanel">
<asp:Table ID="Table1" runat="server" Width="100%">
<asp:TableHeaderRow ID="TableHeaderRow10" runat="server">
<asp:TableCell ID="TableHeaderCell" runat="server"
Font-Bold="true" HorizontalAlign="Center">
Title Text
</asp:TableCell>
</asp:TableHeaderRow>
<asp:TableRow>
<asp:TableCell HorizontalAlign="Center">
<asp:Image ID="Image1" runat="server" ImageUrl="~/Images/animated_progress.gif" />
</asp:TableCell>
</asp:TableRow>
</asp:Table>
<div class="iframeOverlay">
<iframe id="IframeDetail" runat="server" style="width: 100%; height: 100%;" />
</div>
</asp:Panel>
.iframeOverlay
{
z-index: 2;
position: relative;
top: -50px;
}
With Jquery.
<script>
$(document).ready(function() {
$('#<%= UpdateProgress1.ClientID %>').show();
});
</script>
<script> $(document).ready(function() { $('#<%=
UpdateProgress1.ClientID %>').show(); }); </script>
This worked well for me, just had to add it to the end of the BODY section and works like a charm.

jQuery's $() function always returns 'undefined' with AJAX

i've noticed that popup shows BEFORE text gets updated in the textbox, i guess js gets called before the page gets rendered ... that would explain the 'undefined' popup ... how do i make sure js gets called AFTER the page is rendered?
rewriting to make it as simple as possible:
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="txtRcaNotes" runat="server" TextMode="MultiLine" Width="800px"></asp:TextBox><br />
<asp:Button ID="btnDoneWithRcs" runat="server" OnClick="btnDoneWithRcs_Click" Text="Action Completed / Update Notes" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
<script type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(
function(){doStuff();}
);
function doStuff()
{
$(document).ready(function() {
$('txtRcaNotes').hide();
alert($('txtRcaNotes').attr('id'));
});
}
</script>
</body>
Code Behind:
protected void btnDoneWithRcs_Click(object sender, EventArgs e)
{
txtRcaNotes.Text += "asdfadf";
}
TEXTBOX DOESN'T GET HIDDEN, ALERT() RETURNS 'UNDEFINED'
You're just missing your id selector syntax. Try:
$('#<%= txtRcaNotes.ClientID %>').hide();
alert($('#<%= txtRcaNotes.ClientID %>').attr('id'));
Note the addition "#" prepended before each selector.
One thing you could try is using Firebug, or some other DOM inspector and check the actual element IDs that are being generated by ASP.NET before and after your AJAX call and see if they are the same.

Resources