Update Panel and triggers from a repeater control - asp.net

Hi I found code similiar to the following online. It's seems really great for getting a button buried in a repeater control to trigger a full cycle back to the server.
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<%=DateTime.Now.ToString() %>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="HiddenButton" />
</Triggers>
</asp:UpdatePanel>
<!--Make a hidden button to treat as the postback trigger-->
<asp:Button ID="HiddenButton" runat="server" Style="display: none" Text="HiddenButton" />
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
<ItemTemplate>
<!--when cick the button1, it will fire the hiddenButton-->
<asp:Button ID="Button1" Text="Trigger" CommandArgument='<%# Eval("Id") %>' OnClientClick="$get('HiddenButton').click();return false;"
runat="server" />
</ItemTemplate>
</asp:Repeater>
It uses a hiddenButton to achieve this by hooking the click event of the original button to this one. However my addition to this was the setting of the CommandArgument for the button. I would also need it to be set for the HiddenButton.
Does anyone know a way of going about this?

First I will like to explain the Disadvantage of using the Update Panel using the very same example posted by you.
Below is the Original Code
Output
To display the 22 character string you can check how much data is being received and sent to server. Just imagine following
If you would consider send each request to Database using Update Panel and your GridView is in Update Panel!!!!!!
Suppose you would use ViewState data for each request and with GridView Inside the Update Panel.
Both the above techniques are worst as per my understanding.
Now I will describe you Page Methods
Page Method over Update panel
Page Methods allow ASP.NET AJAX pages to directly execute a Page’s Static Methods, using JSON (JavaScript Object Notation). Instead of posting back and then receiving HTML markup to completely replace our UpdatePanel’s contents, we can use a Web Method to request only the information that we’re interested.
Sample Code
Output
Hope this clearly explains the difference of usage.
Answer to the original Query
You have to register the ItemDataBound event of the below Repeater and use below code for it.
Code Behind
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
Button btn = (Button)e.Item.FindControl("Button1");
btn.OnClientClick = string.Format("SubmitButton('{0}');return false;"
, HiddenButton.ClientID);
}
}
JavaScript
<script type="text/javascript">
function SubmitButton(btn)
{
$("#" + btn).click();
}
</script>
//Alternative
<script type="text/javascript">
function SubmitButton(btn)
{
document.getElementById(btn).click();
}
</script>
Reference & Here

Your HiddenButton control is a server control but you are trying to access it in JQuery using it's ASP.Net ID,
<asp:Button ID="Button1" Text="Trigger" CommandArgument='<%# Eval("Id") %>' OnClientClick="$get('**HiddenButton**').click();return false;"
runat="server" />
A quick way to fix it is to make a separate function,
<script type="text/javascript">
function SubmitButton(btn)
{
$get("#" . btn).click();
}
</script>
and change your button code to ,
<asp:Button ID="Button1" Text="Trigger" CommandArgument='<%# Eval("Id") %>'
runat="server" />
In code behind, in repeater's ItemDataBound event, find the button and HiddenControl and set Button1's OnClientClick property,
Button1.OnClientClick= string.Format("SubmitButton('{0}');return false;",HiddenButton.ClientID);

Related

How to use a custom ValidatorUpdateDisplay function when the controls / validators are loaded on postback in an UpdatePanel the first time?

In ASP.NET when using validation controls (i.e. RequiredFieldValidator) the client sided framework will execute the JS function Page_ClientValidate. This function will validate all controls on the page (of the given ValidationGroup) and call the JS function ValidatorUpdateDisplay with a parameter of the DOM element of the span tag of the validator control.
ValidatorUpdateDisplay toggles the visibility of the span tag depending on the result of the validation.
In my web application I've overridden the ValidatorUpdateDisplay JS function to provide more functionality on the validation scenario (i.e. red borders around the controls, showing popover on the first failed control and scrolling to it).
Now this works very well until my controls (incl. submit button) are shown the first time after a postback in an UpdatePanel.
<asp:ScriptManager runat="server" />
<asp:UpdatePanel ID="upTest" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Button ID="bShow" runat="server" UseSubmitBehavior="false" Text="SHOW" OnClick="bShow_Click" />
<asp:Panel ID="pContent" runat="server" Visible="false">
<asp:TextBox ID="tbTest" runat="server" />
<asp:RequiredFieldValidator ID="rfvTest" runat="server" ControlToValidate="tbTest" Text="Not valid" />
<asp:Button ID="bTest" runat="server" UseSubmitBehavior="false" Text="TEST" />
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
<script type="text/javascript">
function ValidatorUpdateDisplay(val) {
debugger; // this will not be reached
}
</script>
protected void bShow_Click(object sender, EventArgs e)
{
this.pContent.Visible = true;
}
After initial load press bShow to display pContent.
Now, if you leave tbTest.Text empty and press on bTest it should enter the overridden ValidatorUpdateDisplay function, however it enters the function of the framework and displays "Not valid" from rfvTest.
If you change pContent.Visible to true and press bTest after initial load the desired effect will happen: It will enter the custom ValidatorUpdateDisplay function and not display "Not valid".
If you move the button bTest out of the UpdatePanel the problem persists.
How can I make it work inside an UpdatePanel?
ASP.NET uses a lazy loading approach to insert the ValidatorUpdateDisplay function when it needs it the first time, hence in my example it will load the function after the postback of the UpdatePanel.
This will override my own implementation of the ValidatorUpdateDisplay function, because it's inserting the function at the end of the page.
There is a dirty workaround, I just inserted an empty CustomValidator on initial load that is always valid:
<asp:CustomValidator runat="server" />
I wish there was a cleaner solution.

How DropDownList's SelectedIndexChanged() works without PostBack?

DropDownList's SelectedIndexChanged() Event fills the ListBox on the page. Obviously this posts the page back to the server. Is there any way to make it happen without full postback?
protected void ddlTablo_SelectedIndexChanged(object sender, EventArgs e)
{
List<string> list = new List<string>();
ListBox1.Items.Clear();
var columnNames= from t in typeof(Person).GetProperties() select t.Name;
foreach (var item in columnNames)
{
list.Add(item);
}
ListBox1.DataSource = list;
ListBox.DataBind();
}
You could put the DropDownList into an <asp:UpdatePanel> and set the trigger to the SelectedIndexChanged event of the DropDownList.
Something like this (don't forget the script manager)
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:DropDownList ID="drop1" runat="server" OnSelectedIndexChanged="ddlTablo_SelectedIndexChanged" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostbackTrigger ControlID="drop1" EventName="SelectedIndexChanged" />
</Triggers>
</asp:UpdatePanel>
You can send ajax call, using asp.net UpdatePanel or use jQuery ajax. This wont do postback and your whole page wont get refreshed.
The UpdatePanel is quite straight forward and easy to use. ASP.net ajax will generate the asyn calls for you whereas jQuery ajax will probably need you to render html using javascript.
In the code snippet below, add this parameter: AppendDataBoundItems="True"
<asp:DropDownList ID="ddlGroupNameFilter"
runat="server"
AutoPostBack="true"
AppendDataBoundItems="true"
OnSelectedIndexChanged="ddlLeadgroupName_SelectedIndexChange">
</asp:DropDownList>

how to make a validation code for ASP.NET form with VB coding

im trying to build a form+attachment that needs to be send to email.
Im using a VB background code (attachementemail.aspx.vb)
and my front (b-16.aspx)
I want the page to check that the user entered a email, name, phonenumber and attachment.
what command do I put in the axp.vb
and what on the .aspx
tried just about anything.
The simplest way is to use validators eg RequiredFieldValidator for mandatory fields. You can also implement CustomValidators for custom logic.
See http://msdn.microsoft.com/en-us/e5a8xz39.aspx for the available validators
At it's basic level you could use RequiredFieldValidator and CustomValidation in your form. You can use some regex logic for email, I use this but there are many out there:
Regex(#"\w+([-+.]\w+)#\w+([-.]\w+).\w+([-.]\w+)*")
Personally I use client side javascript before it hits the server and then I re-validate the entries once it hits the server. If your using the postback events then you'll need update panels and a scriptmanager (not sure if you are aware of this already, so apologies if teaching you to suck eggs!).
Here is an example:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
ErrorMessage="RequiredFieldValidator" ControlToValidate="TextBox1"></asp:RequiredFieldValidator>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
Code behind (sorry this is in c#)
protected void Button1_Click(object sender, EventArgs e)
{
if (RequiredFieldValidator1.IsValid)
{
Label1.Text = "Has content";
}
else
{
Label1.Text = "Not valid";
}
}
Note that the required field validator has it's own methods to display a "hey you haven't entered content here my friend" message, but i have added that to the label instead.

RadioButtonList inside UpdatePanel inside Repeater, Can I?

I have a repeater with a RadioButtonList inside the ItemTemplate, but when the RadioButtonList.OnSelectedIndexChanged event fires it generates a full postback. What have I done wrong in my code below? How can I get the OnSelectedIndexChanged to generate an Async Postback?
<asp:UpdatePanel runat="server" ID="UpdatePanel2">
<ContentTemplate>
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="sqlOptions">
<ItemTemplate>
<asp:UpdatePanel runat="server" ID="pnlA">
<ContentTemplate>
<strong>
<%# Eval("Name") %></strong><br />
<asp:RadioButtonList ID="RadioButtonList1"
DataSourceID="sqlOptionValues" runat="server"
DataTextField="id" DataValueField="Id" AutoPostBack="true"
OnSelectedIndexChanged="LoadPrice"
ValidationGroup="options" />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
ForeColor="Red" runat="server"
ControlToValidate="RadioButtonList1"
ErrorMessage="Required Field"
ValidationGroup="options" />
<asp:SqlDataSource ID="sqlOptionValues" runat="server"
ConnectionString="<%$ ConnectionStrings:
ConnectionString6 %>"
SelectCommand='<%# "SELECT DISTINCT OptionValue.Name,
OptionValue.Id FROM CombinationDetail
INNER JOIN OptionValue
ON CombinationDetail.OptionValueId = OptionValue.Id
WHERE (OptionValue.OptionId =" +
Eval("Id") + ")" %>'>
</asp:SqlDataSource>
<br />
</ContentTemplate>
</asp:UpdatePanel>
</ItemTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
Many thanks for any help :)
This is a real-world use case. I have a page with Repeaters, Ajax Accordions inside of other Accordions, Update Panels inside other Update panels, you name it. The page works great, except when I want to update one of the Accordion panels with my RadioButtonList (RBL). Even with the RBL inside an update panel, it causes a postback of the entire page. I tried everything. I finally realized it wasn't me when I noticed my buttons would work just fine. I figure it must be a bug in either the framework or the Ajax Control Toolkit. I did find people reference this link all over the web (http://blog.smarx.com/posts/the-case-of-the-radiobuttonlist-half-trigger.aspx), but this link from 2007 is dead now and probably no longer applicable, so that's no help.
What I ended up doing was going with what works - that submit button. All I did was add an onclick attribute to the RBL to call a hidden button. Now you don't want to set the button to Visible=false because then the button won't appear in the generated markup. Instead, set the button's style to display:none; so that no one will see this hack, because yes, that's what this workaround is - it's a hack, but simple and just as effective as what you'd expect. Don't forget to remove the Autopostback="True" from your RBL.
CAVEAT: Because I'm using a hacked button for the onclick event, it's possible for the user to click in the area of the RBL, but not actually select an item. When this happens, our onclick triggers an AsyncPostBack and the codebehind logic will be processed, so please keep that in mind. To give you an idea of what I mean: all the Page_Load() events will be called, but rbl_Questions_SelectedIndexChanged() won't be if they happen to click in the area of the RBL without actually selecting an item. For my purposes this causes no issues in my logic and has no effect on the user.
Here's the Code:
Somewhere In the .Aspx Page:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:RadioButtonList ID="rbl_Questions" runat="server"
OnSelectedIndexChanged="rbl_Questions_SelectedIndexChanged">
</asp:RadioButtonList>
<asp:Button ID="btn_rbl_Questions" runat="server" style="display:none;"/>
<asp:Label ID="lbl_Result" runat="server" Text="" Visible="false">
</asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
In the Page_Load() event:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
//Instead of using the AutoPostback of the RBL, use this instead.
rbl_Questions.Attributes.Add("onclick",
"document.getElementById('"
+ btn_rbl_Questions.ClientID
+ "').click();");
//Bind your RBL to a DataSource, add items programmatically,
// or add them in the aspx markup.
}
}
In the rbl_Questions_SelectedIndexChanged() event:
protected void rbl_Questions_SelectedIndexChanged(object sender, EventArgs e)
{
//Your code here.
//My code unhid the lbl_Result control and set its text value.
}
Update 05/24/2011
The above "hack" is no longer necessary (I am leaving it above since this was marked as the answer by the author). I have found the best way to do this, thanks to this SO Answer:
Updatepanel gives full postback instead of asyncpostback
The code is much simpler now, just remove what I put in the Page_Load() method and remove the Button I used in the Aspx page and add ClientIDMode="AutoID" and AutoPostBack="True" to the control you want the UpdatePanel to capture.
Somewhere In the .Aspx Page:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:RadioButtonList ID="rbl_Questions" runat="server"
ClientIDMode="AutoID" AutoPostBack="true"
OnSelectedIndexChanged="rbl_Questions_SelectedIndexChanged">
</asp:RadioButtonList>
<asp:Label ID="lbl_Result" runat="server" Text="" Visible="false">
</asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
MS changed how ClientID's are generated in .net 4.0 from "AutoID" to "Predictable" and I guess the ScriptManager or UpdatePanel's weren't updated correctly to use it. I can't find documentation on why that is anywhere or if it was left that way by design.
I seriously don't miss winforms.
Try this:
<asp:UpdatePanel runat="server" UpdateMode="Conditional" ID="pnlA">
You'll also need to setup
<Triggers>
//radio buttons
</Triggers>
Not sure how you'll do that since it's a dynamically built list.

Postback problem when PopupExtender is placed inside a user control

I am creating a ModalPopupExtender inside a Web User Control.
When i click on the OK Button in the panel, which is showing as model popup, the Event Handeler of the button is not executing.
This problen does not occure when i do not use the Web User Control.
Here is the user control (.ascx) file code.
<script type="text/javascript" language="javascript">
function OkClicked(sender, e) {
__doPostBack('Button1', e);
}
</script>
<asp:Button ID="Button2" runat="server" Text="Show" />
<asp:Panel ID="Panel1" runat="server">
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
</asp:Panel>
<asp:ModalPopupExtender ID="ModalPopupExtender1" runat="server"
DropShadow="True" OkControlID="Button1" PopupControlID="Panel1"
TargetControlID="Button2" onokscript="OkClicked()">
</asp:ModalPopupExtender>
<p>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</p>
And the Event Handeler for the click event of the 'Button1' is
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = TextBox1.Text;
}
In the javascript you shouldn't put 'Button1' as the name of the control. Instead, on the PreRender event of your control, fill that out with this.Button1.ClientID .
ClientID is the unique identifier across the entire generated page of your button control, allowing the server to pinpoint exactly what control triggered the postback.
If this wasn't like that, you wouldn't be able to place multiple instances of a same control on one page.
In code:
<script type="text/javascript" language="javascript">
function OkClicked(sender, e) {
__doPostBack('<%= this.Button1.ClientID %>', e);
}
Couple of suggestions:
Do you have any kind of validation on this page. If so, then it's possible that when you click the ok button, that validation is failing. When you click the button, likely the ModalPopup Extender will close, and if validation fails it may cancel the event happening. If this is the case, add an attribute: CausesValidation="false"
If that doesn't work, you may add an attribute to MAKE it post back, I believe there's an attribute -> AutoPostBack="true".
#Joachim is correct that you'll need to use the clientID, but at the same time, I don't think you'll need to call javascript to run the backend code.
Also, you may consider putting this into an UpdatePanel so that you do an AJAX postback without sending the entire page back and forth when the page is posted back.

Resources