Popup JQuery modal on dropdownlist selectedindexchanged event - c#

I have a requirement to do some logic execution upon change of dropdownlist value. Before executing the logic i need to take user confirmation and then call server side method to complete the process. Not sure How to call server side method based on modal popup confirmation response from user. So if user confirms with Yes button on the modal popup server side code should be called otherwise do nothing.
Here is the code i have . Server side does not get called upon modal popup confirmation.
function PopupDialog(title, text) {
var div = $('<div>').html('<br>'+text).dialog({
title: title,
modal: true,
height: 190,
width: 320,
buttons: {
"Yes": function () {
$(this).dialog('close');
},
"No": function () {
$(this).dialog('close');
}
}
});
return true;
};
<asp:GridView runat="server" ID="grdTransactions" SkinID="gridviewskin"
AllowSorting="true" AllowPaging="true" PageSize="30" Width="100%"
OnRowDataBound="grdTransactions_RowDataBound"
OnDataBound="grdTransactions_DataBound"
OnSelectedIndexChanged="grdTransactions_SelectedIndexChanged">
.............
<asp:TemplateField Visible="true" HeaderText="Status" >
<ItemTemplate>
<asp:Label runat="server" ID="lblStatus" Visible="False" Text='<%# ShowStatus( Container.DataItem ) %>' />
<asp:DropDownList ID="ddlTransactionList" AutoPostBack="True" OnSelectedIndexChanged="ddlTransactionList_SelectedIndexChanged" onchange="return PopupDialog('Remittance Confirmation','Are you sure you want to update the status?.');" runat="server"></asp:DropDownList>
<br/>
</ItemTemplate>
</asp:TemplateField>
The server side code is below:
protected void ddlTransactionList_SelectedIndexChanged(object sender,
EventArgs e)
{
//Your Code
if (OnDataChanged != null)
OnDataChanged(sender, e);
}

Check the generated HTML code of your page and have a closer look on your dropdown. It should look like this:
<select name="gridView$ctl02$ddlTransactionList" onchange="return PopupDialog('Remittance Confirmation','Are you sure you want to update the status?.');setTimeout('__doPostBack(\'gridView$ctl02$ddlTransactionList\',\'\')', 0)" id="gridView_ddlTransactionList_0">
The problem is that you "return" the outcome of your PopupDialog so that the __doPostback function (AutoPostBack) has no chance of getting called. My advice: Only return if the user rejects the change. If the user agrees dont return anything.
Edit (forgot post the solution code)
<asp:DropDownList ID="ddlTransactionList" AutoPostBack="True" OnSelectedIndexChanged="ddlTransactionList_SelectedIndexChanged" onchange="if(! PopupDialog('Remittance Confirmation','Are you sure you want to update the status?.')){return false;}" runat="server"></asp:DropDownList>

Related

Handling click event without postback

I have a listview that populates with data. This listview is inside a user control which sits inside a page called Preferences.aspx. Today I am handling click event on each row meaning that involves posting back to server.
Now, I have to put another user control on Preferences.aspx because there are group of more settings which need to be presented separately to users. I have added the new user control inside a separate tab on the page. This new tab has to be the first one to show when user lands on Preferences.aspx.
Now the problem is that when user goes to second tab (user control with listview) and click on a row, a postback occurs. This puts the user on the first tab (newly added user control).
So I wonder how can I get click event on a row without having to postback?
Any ideas or suggestions are welcome.I am working in Asp.Net with C#.
The code is:
Markup inside the user control:
<asp:TableRow runat="server" id="trVisitor" CssClass='<%# GetRowClass() %>' >
<asp:TableCell ID="tdPicture" runat="server" Width="10" onclick='<%# GetClickPostBack(Container.ItemIndex) %>'>
<div style="margin-top:1px;">
<asp:Image ImageUrl=' <%# Page.ResolveUrl("~/" + Eval("Visitor.StatusImageUrl")) %>' visible='<%# historyFlag ? false : true %>' runat="server"/>
</div>
</asp:TableCell>
... and so on
Markup inside Preferences.aspx:
<ABC:ListControl runat="server" ID="visitorListControl" CanSelect="true" IsMine="true" Recurring="false" OnVisitorSelected="ListControl_VisitorSelected" />
And code behind is:
protected string GetClickPostBack(int itemIndex)
{
if (CanSelect)
//return 0.ToString();
return "javascript: " + Page.ClientScript.GetPostBackEventReference(this, VisitorRowPrefix + itemIndex) + "; return false;";
else
return string.Empty;
}
public void RaisePostBackEvent(string eventArgument)
{
if (eventArgument.StartsWith(VisitorRowPrefix))
{
HandleRowClick(Convert.ToInt32(eventArgument.Substring(VisitorRowPrefix.Length)));
}
}
private void HandleRowClick(int index)
{
int CmgVisitorId = Constants.NotConfigured;
// bool IsHistoricVisitor = false;
// Visitor HistoricVisitor = new Visitor();
// Mark only the clicked row
... and so on.
Hook up to the grid button's click event using JavaScript/jQuery, and prevent theirs default behaviour (post-back) by 2 possible means:
return false;
e.preventDefault (jQuery only)
Example (using jQuery):
$('.button').click(function(event){
event.preventDefault();
//Write your client-side logic here
});
Description: If this method is called, the default action of the event
will not be triggered.
If I am understanding the issue properly, try an update panel.
Check out the documentation here.
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:TableRow runat="server" id="trVisitor" CssClass='<%# GetRowClass() %>' >
<asp:TableCell ID="tdPicture" runat="server" Width="10" onclick='<%# GetClickPostBack(Container.ItemIndex) %>'>
<div style="margin-top:1px;">
<asp:Image ImageUrl=' <%# Page.ResolveUrl("~/" + Eval("Visitor.StatusImageUrl")) %>' visible='<%# historyFlag ? false : true %>' runat="server"/>
</div>
</asp:TableCell>
</ContentTemplate>
</asp:UpdatePanel>

__doPostBack not working inside GridView DropDownList

As topic , I have a item template than consist of a dropdownlist , when user attempt to click it , warning should come out to warn User whether to continue or not. after I click OK , nothing happens , it is not going back to the postback
My gridview code for item template is like the following :
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
<asp:DropDownList ID="cboStatus" runat="server" AutoPostBack="True">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
My Code behind will set the JavaScript to the attribute
DropDownList cboStatus= (DropDownList)e.Row.FindControl("cboStatus");
cboStatus.Attributes.Add("onChange", "Confirmation();");
JavaScript :
function Confirmation() {
if (confirm('Are you sure you want to do this?')) {
__doPostback(this, 'Select${0}');
}
}
I want my postback to call this function
protected void cboStatus_Click(object sender, EventArgs e)
{
//Some Code
}
Change your code a bit like below. This has been tested locally to be working fine. The below code will fire up the server event for selection changed if Ok from the confirmation window is clicked otherwise not.
Your gridview template definition
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
<asp:DropDownList ID="cboStatus" runat="server" AutoPostBack="true" onchange="return Confirmation ();" OnSelectedIndexChanged="cboStatus_SelectedIndexChanged">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
JavaScript function for the onchange event
function Confirmation() {
if (confirm('Are you sure you want to do this?')) {
__doPostBack('__Page', '');
}
return false;
}
And finally your server event for SelectedIndexChanged
protected void cboStatus_SelectedIndexChanged(object sender, EventArgs e)
{
// Some code
}

Viewstate not preserved when handling exception

I'm using a detailsview for a dialog to the user, and it seems that the viewstate is not preserved when there is an error inserting the data.
I'm using a OnInserted handler on the datasource to check if there was an exception like so:
protected void areaInsertHandler(Object sender, SqlDataSourceStatusEventArgs e)
{
if (e.Exception != null)
{
// There was an error in submitting, show the error dialog
ScriptManager.RegisterClientScriptBlock(Page, GetType(), "DialogHandler", "showError('#overlayAreas');", true);
e.ExceptionHandled = true;
}
}
Which simply calls the client side JS function:
function showError(overlayName) {
$(".msgError").css('visibility', 'visible');
$(overlayName).css('visibility', 'visible');
}
My detailsview looks something like this:
<asp:UpdatePanel ID="AreaUP" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<div id="overlayAreas" class="overlay">
<asp:DetailsView
ID="DetailsView_Areas"
runat="server"
Visible="True"
AutoGenerateInsertButton="False"
AutoGenerateRows="False"
caption="<a style='font-weight: bold;'>Bold</a> = Required field"
CaptionAlign="Bottom"
headertext="Create new area"
EnableViewState="true"
DataKeyNames="Area_Name"
DataSourceID="AreasSource"
DefaultMode="Insert">
<Fields>
...
</Fields>
</asp:DetailsView>
</div>
<br />
<asp:Button width="200" height="30" ID="Button_CreateArea" runat="server" OnClientClick="return btnToggle('#overlayAreas')" Text="Create new area" />
</ContentTemplate>
</asp:UpdatePanel>
It all works fine, but for some reason the ASP viewstate is not preserved. Meaning that if I fill out incorrect information in the form and submit I will get the appropriate error and the dialog will still be displayed. But the fields are not filled out with my old values.
If someone could give me some pointers or help me out I'd greatly appreciate it
EDIT 10-08: Still haven't been able to solve it, any ideas at all?
basically:
avoid DetailsView_Areas.DataBind()
if (DetailsView_Areas.CurrentMode != DetailsViewMode.Insert) DetailsView_Areas.DataBind();
create the ItemInserted event for your DetailsView_Areas and put
if (e.AffectedRows < 0) e.KeepInInsertMode = true;
see http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.detailsviewinsertedeventargs.affectedrows(v=vs.110).aspx

asp.net c# validation

I am trying to create a simple form that uses radio buttons. I set the radio button to AutoPostBack = True, this way if the radio button is true/false, a subpanel is Shown or Hidden. The radio buttons are required fields. I also have a hidden textbox that the value of the selected radio button is inserted and this textbox is what I validate against (empty or not).
Problem 1:
This works until you go to submit and the validation fails. The validation messages show, then when you click on one of the radio buttons with AutoPostBack = True, all the validation disappear. I can resolve this by adding Page.Validate() to the method that runs when the radio button is clicked. But, I do not want the Page.Validate() to run unless the page was already showing validation errors (so it will not re-validate unless the form was already submitted and failed the validation).
As it stands, before the form is submitted and fails validation: when you click on any radio button question, all the other questions requiring validation show the validation error. I am only looking to overcome the AutoPostBack which is clearing all the validation messages that are shown when you had click submit.
Problem 2:
I would like to be able to change the color of the question if it does not pass validation. I added the javascript to override the default .net settings. I got this to work, but only when you click the submit button and not after a RadioButton AutoPostBack.
Currently, When you click submit all the required questions turn red and also display the required validation message. But if you click a radio button to start fixing the validation errors, on the AutoPostBack, the all the questions that were now red in color changes back to the orignal black and the required validation message is still shown. How can I call the Javascript to run again along with the Page.Validation() in the code behind method?
Any help would be greatly appricated! Thanks
Below is an example of the code so far.
ASPX Code:
<asp:Table ID="Table1" runat="server" CellSpacing="0" CellPadding="0">
<asp:TableRow>
<asp:TableCell CssClass="question">
<label>4. Have you had an abnormal result from a prenatal test (e.g. amniocentesis, blood test, ultrasound)?</label>
</asp:TableCell>
<asp:TableCell CssClass="answer">
<ul class="selectGroup">
<li>
<asp:RadioButton ID="Q4_true" runat="server" Checked='<%# Bind("Q4_yes") %>' Text="Yes"
GroupName="4" OnCheckedChanged='RB_QuestionSubPane_YN' AutoPostBack="true" /></li>
<li>
<asp:RadioButton ID="Q4_false" runat="server" Checked='<%# Bind("Q4_no") %>' Text="No"
GroupName="4" OnCheckedChanged='RB_QuestionSubPane_YN' AutoPostBack="true" />
</li>
<asp:TextBox ID="Q4_validationBox" runat="server" CssClass="hiddenField" Enabled="false"
Text=''></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" EnableViewState="true" ControlToValidate="Q4_validationBox"
Display="Dynamic" runat="server" ErrorMessage="RequiredFieldValidator"></asp:RequiredFieldValidator>
</ul>
</asp:TableCell>
</asp:TableRow>
</asp:Table>
Code Behind
protected void RB_QuestionSubPane_YN(object sender, EventArgs e)
{
RadioButton radio_Selected = (RadioButton)sender;
string radio_QuestionID = Convert.ToString(radio_Selected.ID);
(((TextBox)FormView1.FindControl(strQuestionID + "_validationBox")).Text) = radio_Selected.ID.ToString();
Page.Validate();
}
JavaScript
ValidatorUpdateDisplay = function (val) {
var ctl = $('#' + val.controltovalidate);
var eCount = 0;
for (var i = 0; i < Page_Validators.length; i++) {
var v = Page_Validators[i];
if (v.controltovalidate == val.controltovalidate) {
if (!v.isvalid) {
eCount++;
ctl.addClass('validationError');
$('td.question:eq(' + i + ')').addClass('red');
}
};
}
if (eCount > 0) {
ctl.addClass('validationError');
} else {
ctl.removeClass('validationError');
$('td.question:eq(' + i + ')').removeClass('red');
}
if (typeof (val.display) == "string") {
if (val.display == "None") {
return;
}
if (val.display == "Dynamic") {
val.style.display = val.isvalid ? "none" : "inline";
return;
}
}
if ((navigator.userAgent.indexOf("Mac") > -1) &&
(navigator.userAgent.indexOf("MSIE") > -1)) {
val.style.display = "inline";
}
val.style.visibility = val.isvalid ? "hidden" : "visible";
}
It sounds like what you really need is custom validation. That way you can fully customize your validation to meet your needs.
Here is a simple example:
<script language="javascript" type="text/javascript" >
function CustomValidator1_ClientValidate(source,args)
{
//put your javascript logic here
}
//-->
</script>
<body>
<form id="form1" runat="server">
<div>
<asp:RadioButton ID="RadioButton1" runat="server" GroupName="direction" Text="left" />
<asp:RadioButton ID="RadioButton2" runat="server" GroupName="direction" Text="right" />
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
<asp:CustomValidator id="CustomValidator1" runat="server" Display="Dynamic" ErrorMessage="please choose" ClientValidationFunction="CustomValidator1_ClientValidate" OnServerValidate="CustomValidator1_ServerValidate"></asp:CustomValidator>
</div>
</form>
</body>
Server Side
protected void CustomValidator1_ServerValidate(object source, ServerValidateEventArgs args)
{
args.IsValid = RadioButton1.Checked || RadioButton2.Checked;
}
protected void Button1_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
//validate is successful.
}
}

AJAX ToolKit TabContainer: Can I capture the "Active Tab Panel Changing" event

I have an AJAX ToolKit TabContainer control with several TabPanels. I want to validate the contents of the current active TabPanel to prevent user from working on other ones in case data was invalid.
If you need to do a TabPanelChangingEvent SERVER side, You will need to do this by Altering the ajaxcontroltoolkit Source code.
Good news : you could easily get it
Here a new solution that does almost what your need :
The OnClientActiveTabChanged event is raised
The tabcontainer New Tab index is saved in a Hiddenfield
The tabindex is reset to it's old value (so it wont change right now)
The form trigger a asyncpostback using a hidden button.
Within the hidden button's Click event, the OldTabIndex and NewTabIndex are retrieved.
At the end of the Click event, the tabcontainer's tabindex is switched to the new value.
So, the hidden button's Click event is executed before the TabContainer tab is changed.
aspx:
<asp:Button runat="server" ID="hiddenTargetControlForTabContainer" style="display:none" />
<asp:UpdatePanel ID="TabContainerUpdatePanel" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="hiddenTargetControlForTabContainer" />
</Triggers>
<ContentTemplate>
<asp:HiddenField ID="TabContainerActiveTab" runat="server" Value="0" />
<AjaxControlToolkit:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="0"
OnClientActiveTabChanged="OrderTabContainerClientActiveTabChanged" >
<AjaxControlToolkit:TabPanel runat="server" ID="TabPanel1"
HeaderText="TabPanel1"
>
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</ContentTemplate>
</AjaxControlToolkit:TabPanel>
<AjaxControlToolkit:TabPanel runat="server" ID="TabPanel2"
HeaderText="TabPanel2" >
<ContentTemplate>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
</ContentTemplate>
</AjaxControlToolkit:TabPanel>
</AjaxControlToolkit:TabContainer>
</ContentTemplate>
</asp:UpdatePanel>
<script type="text/javascript">
var TabContainerActiveTabControlID = '<%= TabContainerActiveTab.ClientID %>';
var hiddenTargetControlForTabContainerControlID = '<%= hiddenTargetControlForTabContainer.uniqueID %>';
function OrderTabContainerClientActiveTabChanged(sender, args) {
var TabContainerActiveTabControl = $get(TabContainerActiveTabControlID);
var OldtabIndex = parseInt(TabContainerActiveTabControl.value);
var NewtabIndex = sender.get_activeTabIndex();
if (!(OldtabIndex == NewtabIndex)) {
sender.set_activeTabIndex(OldtabIndex);
TabContainerActiveTabControl.value = NewtabIndex;
__doPostBack(hiddenTargetControlForTabContainerControlID, '');
}
}
Code behind:
Protected Sub hiddenTargetControlForTabContainer_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles hiddenTargetControlForTabContainer.Click
Dim oldActiveTabIndex = TabContainer1.ActiveTabIndex
Dim newActiveTabIndex As Integer = Convert.ToInt32(TabContainerActiveTab.Value)
'your stuff here
TabContainer1.ActiveTabIndex = newActiveTabIndex
End Sub
Problem: Ajax TabContainer the ActiveTabChanged event shows incorrect ActiveTabIndex.
For eg. TabContainer contain 3 tabs, if second tab is hide(visible = false on server side) then on click of third tab, we get ActiveTabChanged = 1 not 2 (expected active index is 2 on server side code).
Solution:
Register the clientside event of the tab container:
OnClientActiveTabChanged="Tab_SelectionChanged"
Then define the javascript function to handle the above event which will internally store the tab index in a hidden variable.
function Tab_SelectionChanged(sender,e)
{
document.getElementById('<%=hdntabIndex.ClientID %>').value = sender.get_activeTabIndex();
}
Use the hidden variable(hdntabIndex) in the code behind where ever you need the active tab index.
You should do it using JavaScript.
Here an example I made, the trick is to use ValidationGroup and save the Old tab Index at the end of the function called by the OnClientActiveTabChanged
<AjaxControlToolkit:TabContainer ID="TabContainer1" runat="server" Height="138px"
Width="402px" ActiveTabIndex="0"
OnClientActiveTabChanged="ValidateTab" >
<AjaxControlToolkit:TabPanel runat="server" ID="TabPanel1"
HeaderText="TabPanel1"
>
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
ErrorMessage="RequiredFieldValidator"
ControlToValidate="TextBox1"
ValidationGroup="TabPanel1"
/>
</ContentTemplate>
</AjaxControlToolkit:TabPanel>
<AjaxControlToolkit:TabPanel runat="server" ID="TabPanel2"
HeaderText="TabPanel2" >
<ContentTemplate>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server"
ErrorMessage="RequiredFieldValidator"
ControlToValidate="TextBox2"
ValidationGroup="TabPanel2"
/>
</ContentTemplate>
</AjaxControlToolkit:TabPanel>
</AjaxControlToolkit:TabContainer>
<script type="text/javascript">
var OldtabIndex = 0;
function ValidateTab(sender, args) {
if (OldtabIndex == 0) {
if (!Page_ClientValidate('TabPanel1')) {
sender.set_activeTabIndex(OldtabIndex);
}
}
else if (OldtabIndex == 1) {
if (!Page_ClientValidate('TabPanel2')) {
sender.set_activeTabIndex(OldtabIndex);
}
}
OldtabIndex = sender.get_activeTabIndex();
}
</Script>
I know I'm probably late to answering this question, but hopefully, I can offer some assistance to someone who's pot-committed like I was to the TabPanels.
Add the OnClientActiveTabChanged="showMap" to the ajaxToolkit:TabContainer. My function is obviously called showMap (had to hide and show the Google Street Map, because TabContainer screws it all up. So I had to move the Google Street Map outside of the container and then 'fake' put it back in the container).
<ajaxToolkit:TabContainer runat="server" ID="tabs" OnClientActiveTabChanged="showMap">
<ajaxToolkit:TabPanel runat="server" ID="pnlZones" HeaderText="Delivery Zones">
<ContentTemplate>
...
</ContentTemplate>
</ajaxToolkit:TabPanel>
</ajaxToolkit:TabContainer>
Then create the javascript:
<script type="text/javascript">
function showMap() {
var tabID = $('.ajax__tab_active').attr('id');
if (tabID.indexOf('pnlZone') > 0) {
$('#mapHider').css('height', '600px');
}
else {
$('#mapHider').css('height', '0');
}
}
</script>
We can then find the active tab by the class .ajax__tab active, which is what TabContainer will set the active class to. Snag the ID (.attr('id')) with jQuery... And voila, we now which tab we're currently on.
For this I change the height of the class from 0 to 600px. With the overflow set to hidden, it makes it seem like the map is on the page and only in that container, but it isn't.
Hopefully, this helps!! Good luck.

Categories

Resources