0

I have a Gridview with buttons for removing data rows. I'm trying to implement a modal popup via jQueryUI Dialog so that after clicking "Remove Data" the user gets prompted and if they click yes, the row gets removed, if no, nothing happens. It seems that if I don't add a "return false" to the onClientClick, the row will be removed as soon as the button is clicked, regardless. If I include return false, I'm not sure how I can get the gridviewrow command to actually happen. Here are some current snippets:

In script tag:

function ShowPopup() {
        $(function () {
            var message = "Are you sure you want to Remove Data?";
            $("#dialog").html(message);
            $("#dialog").dialog(
                {
                    title: "Data Removal Confirmation",
                    buttons: {
                        Yes: function () {
                            return true;
                        },
                        No: function () {
                            $(this).dialog('close');
                            
                        }
                    },
                    modal: true
                });
        });
    }

Dialog Div:

<div id="dialog" style="display: none">

Gridview Button:

<asp:TemplateField HeaderText="Reject">
                        <ItemTemplate>
                            <asp:Button
                                ID="btnRemove"
                                runat="server"
                                Text="Remove Data"
                                CssClass="inherited, RemoveData"
                                CommandName="RemoveData"
                                Style="white-space: normal;"
                                 OnClientClick="javascript: ShowPopup();return false;"
                                CommandArgument="<%# ((GridViewRow) Container).RowIndex %>" />
                        </ItemTemplate>
                        <ItemStyle HorizontalAlign="Center"></ItemStyle>
                    </asp:TemplateField>

Codebehind:

else if (e.CommandName == "RemoveData")
                        {
                            
                            
                            int affected = 0;
                            affected = DAL.RemoveFileUploadItem((Guid)Session["UserId"], UploadId.ToString());
                            BindAll();
                            gv_PostUpload.DataSource = null;
string FileName = UploadId.ToString() + "-" + gvDashboard.DataKeys[index]["FileName"].ToString();
                            string mypath = Path.Combine(Global.data_directory, @"Watch"); // Server.MapPath("~/Data/Watch/");
                            string totalfn = Path.Combine(mypath, FileName);
                            if (File.Exists(totalfn))
                                File.Delete(totalfn);
DAL.LogActivity("Attempt removing file " + gvDashboard.DataKeys[index]["FileName"].ToString(), Utilities.GetCurrentPageFromURL(), Session["UserId"].ToString());
                            int affected = 0;
                            affected = DAL.RemoveFileUploadItem((Guid)Session["UserId"], UploadId.ToString());                                        
                            if (affected != 0)
                            {
                                DAL.LogActivity(gvDashboard.DataKeys[index]["FileName"].ToString() + " removed ", Utilities.GetCurrentPageFromURL(), Session["UserId"].ToString());
                            }
                            BindAll();
                            gv_PostUploadZ.DataSource = null;
                            plnView.Visible = false;
                            plnViewZ.Visible = false;
                            plnErrorView.Visible = false;
                        }

Here are the modified buttons based on @albert-d-kallal's answer:

<asp:TemplateField HeaderText="Reject">
                        <ItemTemplate>
                            <asp:Button
                                ID="btnRemove"
                                runat="server"
                                Text="Remove Data"
                                CssClass="inherited, RemoveData"
                                CommandName="RemoveData"
                                
                                CommandArgument="<%# ((GridViewRow) Container).RowIndex %>" />
                        </ItemTemplate>
                        <ItemTemplate>
                        <asp:Button
                        ID="btnRemove2" ClientIDMode="Predictable"
                        runat="server"
                        Text="Remove Data"
                        CssClass="inherited, RemoveData"
                        Style="white-space: normal;"
                        OnClientClick='<%# "ShowPopUp(" + ((GridViewRow) Container).RowIndex + ");return false;" %>' />
                        </ItemTemplate>
                        <ItemStyle HorizontalAlign="Center"></ItemStyle>
                    </asp:TemplateField>

After the above modification, here is what I now am seeing n browser tools when inspecting that the button:

<input type="submit" name="ctl00$mainContent$gvDashboard$ctl02$btnRemove2" value="Remove Data" onclick="ShowPopUp(0);return false;" id="ctl00_mainContent_gvDashboard_ctl02_btnRemove2" class="inherited, RemoveData" style="white-space: normal;">

2 Answers 2

1

Ok, first up? jQuery.ui and MOST web code these days is NON blocking. That means the jQuery.UI dialog DOES NOT halt code. Near all code runs - and runs without blocking (async).

So, if you use anything but the alert() dialog, you can't block code, and return true, or false.

So, what to do?

Well, it means we have to display the dialog, and THEN AFTER the user makes the choice, we have to fire/trigger/click/run code to do the delete.

So, I would suggest that your delete button does NOT run the row index changed, and execute that code. In theory, you would say pass some PK row value to the js on a click. Get the yes/no using the jQuery dialog, and THEN call some code to do the delete.

So, that button can not really return true/false to THEN allow the button code (server side) to run.

I can think of quite a few ways to do this. However, you can trick the grid, and have jQuery "click" on the button AFTER you determined yes (ok) or cancel.

This quite much means we need a "differnt" button. But, we could just "hide" the existing delete button (but leave it in place), and simply place our javascrip button right below that button.

So, lets hide your button with style="display:none" (FYI - can't use visible, since that would mean the browser never renders the button).

So, lets do this:

<asp:TemplateField>
<ItemTemplate>
    <asp:Button
    ID="btnRemove"
    runat="server"
    Text="Remove Data"
    style="Display:none"
    CommandName="RemoveData"
    CommandArgument="<%# ((GridViewRow) Container).RowIndex %>" />
</ItemTemplate>
</asp:TemplateField>

so we style button = none (it will not display). I also removed the CssClass - again since the button is "hidden", we don't care.

Now, lets drop in our button that we REALLY click on!

Lets put it right below above in the markup:

<asp:TemplateField>
<ItemTemplate>
<asp:Button
ID="btnRemove2"
runat="server"
Text="Remove Data"
CssClass="inherited, RemoveData"
Style="white-space: normal;"
OnClientClick='<%# "ShowPopUp(" + Container.DisplayIndex.ToString + ");return false;" %>'
</ItemTemplate>
</asp:TemplateField>

So, above is a dummy button - note the return = false; we don't want it to run any sever side code - and the return = false means no post back occurs.

But, NOTE one big deal? We passed the row index to that click event.

So, our jQuery.ui dialog can now look like this:

      function ShowPopUp(ix) {
            var message = "Are you sure you want to Remove Data?";
            var mydiv = $('#dialog');
            mydiv.html(message);
            mydiv.dialog({
                autoOpen: false, modal: true, title: 'Data Removal Confirmation', width: '30%',
                position: { my: 'top', at: 'top+150' },
                buttons: {
                    'Yes': function () {
                        // first, close the dialog
                        $('#dialog').dialog('close');
                        btn = $('#GridView1_btnRemove_' + ix.toString());
                        btn.click();
                    },
                    'No': function () {
                        $('#dialog').dialog('close');
                    }
                }
            });
            // Open the dialog
            mydiv.dialog('open');
        }

Note how now we have code for the ok, and cancel buttons.
Note how we have to close the dialog.

And note that last whopper - we select the button based on the row, and click it.

Now, I not really sure if above is the best. I would perhaps consider NOT using the fake button click - Might have just as well done a js postback and passed the row index with a postback argument. (this would mean in the page on-load event, you would pick this post-back up - you can google _dopostback().

Note also one did not need the "script" in front of the OnClickClick.

But, the above should work.

So, keep in mind:

the jQuery.ui code is NON blocking - it does not wait. When you call it, it runs right though and THEN displays the dialog - the code does not halt, nor is it blocked. As a result, we can't return true, or false (to allow the server side code to run).

If the jQuery.ui dialog WAS blocking, then the return of true/false could be used - but that code does not block/wait.

But, by passing the row index, we ARE able to select the hidden button, and click() fire it. As noted that's somewhat ok of "approaching a kluge" idea here. However, since you KNOW existing code works, that's why I went with the button click trick here.

I used GridView1, as the grid name - change it to what you are using.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the detailed answer, it's helped me understand this a bit better. I made your changes although I had to modify some of the code as it was interfering with another srcript a bit. Also, you had inconsistent case in the name of the JS function and where it was being called in the button. While I can pass a row number to the jqueryUI function, I'm unable to have the function click the button in question. Now that I'm examining it a bit more, I see that the "hidden" button is not accessible to JS - I can't see it in browser tools - even when I remove the style attribute.
I've posted my modifications above. I had to put the second button within the same templatefield, otherwise the gridview creates an additional blank column, even if Style is set display:none.
Even when I add the button in a separate templatefield so that it's visible, the JS still isn't able to see it based on the gridviewname_buttonid_rowindex format you presented above...
0

Ok, it's a bit hacky, but I was able to use some of @albert-d-kallal's suggestions above, but had to come up with some other code that would anchor the correct rowindex values to the actual buttons that were wired to the .Net event handlers. I did this by just making the "fake/hidden" buttons have a text value of the row index. In order to hide the column that .Net creates for that button, I had to use some custom CSS. Here are the final code snippets:

JS:

function ShowPopUp(ix) {
        $(function () {
            var message = "Are you sure you want to Remove Data?";
            var mydiv = $('#dialog');
            mydiv.html(message);
            mydiv.dialog(
                {
                    //autoOpen: false,
                    title: "Data Removal Confirmation",
                    modal: true,
                    width: '30 %',
                    position: { my: 'top', at: 'top+150' },

                    buttons: {
                        Yes: function () {
                            // first, close the dialog
                            $('#dialog').dialog('close');
                            btn = $("[id$=btnRemove]")[ix.toString()];
                            btn.click();
                        },
                        No: function () {
                            $('#dialog').dialog('close');
                        }
                    },
                    
                });
        });
    }

Item Templates for the buttons:

<asp:TemplateField ControlStyle-CssClass="visiblyHidden" FooterStyle-CssClass="visiblyHidden" HeaderStyle-CssClass="visiblyHidden" ItemStyle-CssClass="visiblyHidden" HeaderText="">
                        <ItemTemplate>
                            <asp:Button
                                ID="btnRemove"
                                runat="server"
                                Text='<%#  ((GridViewRow) Container).RowIndex + "" %>'
                                CssClass="inherited, RemoveData"
                                CommandName="RemoveData" 
                                
                                CommandArgument="<%# ((GridViewRow) Container).RowIndex %>" />
                        </ItemTemplate>
                        <ItemStyle HorizontalAlign="Center"></ItemStyle>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="Reject" FooterStyle-CssClass="rejectHideLeftBorder" HeaderStyle-CssClass="rejectHideLeftBorder" ItemStyle-CssClass="rejectHideLeftBorder">
                        
                        <ItemTemplate>
                        <asp:Button
                        ID="btnRemove2" 
                        runat="server"
                        Text="Remove Data"
                        ClientIDMode="Static"
                        Style="white-space: normal;"
                        OnClientClick='<%# "ShowPopUp(" + ((GridViewRow) Container).RowIndex + ");return false;" %>' />
                        </ItemTemplate>
                        <ItemStyle HorizontalAlign="Center"></ItemStyle>
                    </asp:TemplateField>

CSS:

.visiblyHidden {
width: 0 !important;
padding: 0 !important;
border: 0 !important;
}
 .rejectHideLeftBorder {
border-left: 0 !important;
}

1 Comment

using f12 in the browser, and selecting elements should show button sleect format. Only hide the button AFTER you get this working - as noted, style="Display:none" should not change final render of controls, only hides. VERY important, that if you don't use Command="select", then row index changed does NOT fire. So this command is NOT of your choice - you have to specific use Select, or Delete. If you use custom command, then row index changed will not fire. So, I did NOT have to pass index to the button that I click since everything can be grabbed in the row index changed event.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.