Link to home
Start Free TrialLog in
Avatar of CitySec
CitySec

asked on

Prompt user when leaving a Gridview row in edit mode

If a user is editing a row in my gridview and they decide to navigate away from the row without confirming the update (such as if they click edit on another row) I want to prompt them and confirm if they wish to "exit the row without saving". What is the best way to do this?

Adding javascript to the Cancel button of the row won't accomplish my task because users do not always click Cancel before they attempt to navigate away from the row.

I thought about gvMuniData.RowCancelingEdit, but that event doesn't fire unless they click Cancel on the row. I also tried:

e.Row.Attributes.Add("onblur", "javascript:return confirm('You haven't saved this record. Are you sure you want to exit this row without saving?')")

but I couldn't get the onblur event to fire. Onmouseout fired fine, but I don't want to use that javascript function.
Avatar of ASPSQLServerCOM
ASPSQLServerCOM
Flag of United States of America image

could it be possible for you to paste the code
Avatar of CitySec
CitySec

ASKER


<asp:UpdatePanel ID="updGridview" runat="server">
    <ContentTemplate>                
        <asp:GridView ID="gvMuniData" DataKeyNames="ID" runat="server" AllowPaging="True" AutoGenerateColumns="False" DataSourceID="sqlGridview" AllowSorting="True" OnRowCommand="gvMuniData_RowCommand">            
            <Columns>               
                <asp:BoundField DataField="ID" Visible="False" />
                <asp:TemplateField HeaderText="ID" SortExpression="ID" Visible="False">
                    <EditItemTemplate>
                        <asp:Label runat="server" ID="lblID" Text='<%# Bind("ID") %>'></asp:Label>
                    </EditItemTemplate>
                    <ItemTemplate>  
                        <asp:Label runat="server" ID="lblID" Text='<%# Bind("ID") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                    <EditItemTemplate>
                        <asp:Panel runat="server" ID="gridPopupEdit" CssClass="gridPopupEdit">
                            <div class="floatleft"><asp:imagebutton ID="btnUpdate" runat="server" CommandArgument='<%# Bind("ID") %>' commandname="Update" ImageUrl="images/check.gif" CausesValidation="true" AlternateText="Save Changes" /></div>
                            <div class="floatleft"><asp:imagebutton ID="btnDetails" runat="server" CommandArgument='<%# Bind("ID") %>' commandname="Select" ImageUrl="images/arrow.gif" CausesValidation="false" AlternateText="Details"/></div>
                            <div class="floatleft"><asp:imagebutton ID="btnCancel" runat="server" CommandArgument='<%# Bind("ID") %>' commandname="Cancel" ImageUrl="images/cancel.gif" CausesValidation="false" AlternateText="Cancel Editing"/></div>
                            <div class="floatleft"><asp:imagebutton ID="btnDeleteEdit" runat="server" CommandArgument='<%# Bind("ID") %>' commandname="Delete" ImageUrl="images/delete.gif" CausesValidation="false" AlternateText="Delete"/></div>                        
                        </asp:Panel>                                            
                    </EditItemTemplate>
                    <ItemTemplate>
                        <asp:Panel runat="server" ID="gridPopupNonEdit" CssClass="gridPopup"> 
                            <div class="floatleft"><asp:imagebutton ID="btnEdit" runat="server" CommandArgument='<%# Bind("ID") %>' commandname="Edit" ImageUrl="images/edit.gif" CausesValidation="false" AlternateText="Edit" /></div>
                            <div class="floatleft"><asp:imagebutton ID="btnDetails" runat="server" CommandArgument='<%# Bind("ID") %>' commandname="Select" ImageUrl="images/arrow.gif" CausesValidation="false" AlternateText="Details"/></div>
                            <div class="floatleft"><asp:imagebutton ID="btnDeleteNonEdit" runat="server" CommandArgument='<%# Bind("ID") %>' commandname="Delete" ImageUrl="images/delete.gif" CausesValidation="false" AlternateText="Delete"/></div>                        
                        </asp:Panel>
                    </ItemTemplate>
                </asp:TemplateField>
 
 
...
 
 
 
                <asp:TemplateField HeaderText="Competitive/ Negotiated" SortExpression="CompetitiveNegotiated">
                    <EditItemTemplate>
                        <div class="gvLabel">Comp/Neg</div>
                        <asp:DropDownList runat="server" ID="ddlCompetitiveNegotiated" CssClass="gvDropDownList"></asp:DropDownList>
                        <asp:HiddenField runat="server" ID="hdCompetitiveNegotiated" value='<%# Bind("CompetitiveNegotiated") %>' /> 
                    </EditItemTemplate>
                    <ItemTemplate> 
                        <div title="header=[Competitive/ Negotiated] fade=[off] fadespeed=[.3] cssbody=[boxoverBody] cssheader=[boxoverHeader compNeg]">                           
                            <asp:Label ID="lblCompetitiveNegotiated" runat="server" Text='<%# Bind("CompetitiveNegotiated") %>'></asp:Label>
                        </div>                           
                    </ItemTemplate>
                </asp:TemplateField>           
            </Columns>
        </asp:GridView>
    </ContentTemplate> 
</asp:UpdatePanel>
 
 
 
    Private Sub gvMuniData_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvMuniData.RowDataBound
 
        If e.Row.RowType = DataControlRowType.DataRow Then
 
            If (e.Row.RowState And DataControlRowState.Edit) > 0 Then
 
                e.Row.Attributes.Add("onblur", "javascript:return confirm('You haven't saved this record. Are you sure you want to exit without saving?')")
 
            End If
 
        End If
 
    End Sub

Open in new window

many times browser are very specific to javascript , try onBlur

http://forums.asp.net/t/1228965.aspx

 if (e.Row.RowType == DataControlRowType.DataRow)
            {
                Button btn = e.Row.FindControl("Button1") as Button;
                string script = Page.GetPostBackEventReference(btn, "");

                e.Row.Attribute.add("onblur",script);
             }


Also colud it be possible for you to copy paste the browser view source of page
also try change onblur with onfocus and see that event is getting fired
Avatar of CitySec

ASKER

I have an onclick event and an onfocus event in the row. Here's the VB:

e.Row.Attributes.Add("onclick", ClientScript.GetPostBackClientHyperlink(Me.gvMuniData, "Edit$" + e.Row.RowIndex.ToString))

e.Row.Attributes.Add("onfocus", "javascript:return confirm('You gave focus to this row.')")

And here's the page source for a row:

<tr id="gvMuniData_ctl03" onclick="javascript:__doPostBack('gvMuniData','Edit$0')" onfocus="javascript:return confirm('You gave focus to this row.')" style="background-color:#F0F0F0;">

The click works fine but the focus does not work.
Hi CitySec I dont thnk tr has a onblur function its for the form fields.
You have to add the onblur in the formfields

Harry
Avatar of CitySec

ASKER

OK, so what is the best way to prompt a user when leaving a Gridview row? Basically what I need is a way for the user to be notified when they have left a Gridview row that is in edit mode without saving it. What would be even better is if it would do an autosave when they leave the row. Any way of doing this is appreciated.
hi, <TR will not give you onblur , best is use on your form control like text box
Avatar of CitySec

ASKER

OK, so what is the best way to prompt a user when leaving a Gridview row? Basically what I need is a way for the user to be notified when they have left a Gridview row that is in edit mode without saving it. What would be even better is if it would do an autosave when they leave the row. Any way of doing this is appreciated.
hi,
**********editing a row in my gridview and they decide to navigate away from the row
does your form has any textbox where they are going to change the value then attach event on to that text box, if other control where user is going to change the value then attach event to that control and not to TR
Avatar of CitySec

ASKER

There are around 20 textboxes and dropdownlists in each row. If I attach an event to each of these, it will prompt them to save as they are moving between each input box, right?
use
My suggestion is to put one button in edit template and set it's commandname equals update.

Then you can write some code in RowDataBound event javascript onfocus where it will fire the update button click event

   
in this case, best logic, for every row, attach onfocus/onblur event, assign one constant id value paramter to all the controls for each row
 .......Attributes.Add("onfocus", "javascript:checkFocus(RowNumber')")
means in first row all your text box and drop down control will have id 1, second row all control has id 2 and so on
now in declare one global variable which will hold the current rownumber like
<script = javascript ..........>
var currentEditRowNum=0
now in checkFocus javascript function (RowNum)
{
if currentEditRowNum<> RowNum
......make your prompt
currentEditRowNum= RowNum


i think this will be best way to implement

Avatar of CitySec

ASKER

I was able to implement that but it does not accomplish the task of prompting a user when they leave a gridview row. What it does is it prompts a user when they leave the first control of a new gridview row. It is not able to recognize when the user leaves the row.

The user might leave the row and attempt to do something else besides edit another row (like sort the columns, add a new row, or search the gridview).

Any more ideas?
SOLUTION
Avatar of ASPSQLServerCOM
ASPSQLServerCOM
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of CitySec

ASKER

I was using onblur - you're right. I will give it a shot tomorrow morning. Thanks for all your help. I still think this won't work unless all my gridview rows are in edit mode to begin with, but I'll still give it a try tomorrow.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of CitySec

ASKER

Good job - much closer! Now I just have one last problem and I will mark the solution(s). I already have an onclick event on the row click event which puts the row into edit mode:

e.Row.Attributes.Add("onclick", ClientScript.GetPostBackClientHyperlink(Me.gvMuniData, "Edit$" + e.Row.RowIndex.ToString))

How can I add another click event when there is already one there? It overwrites the first one. The new row click even I would be adding is this:

e.Row.Attributes.Add("onclick", "javascript:return checkEditMode('on')")

And here is the javascript function I came up with based on your solution:

//global variable for edit mode - default is off
var currentEditMode="off";

function checkEditMode(mode) {
    if (currentEditMode=="on") {      //there is currently a row in edit mode
        var answer = confirm("You haven't saved your changes to this row. Are you sure you wish to exit?");
        if (answer){          //we are leaving without saving  
            if (mode=="off") {
                currentEditMode="off";
            } else {
                currentEditMode="on";
            }
        } else {         //we decided not to leave yet
            return false
        }
    } else {      //there is not currently a row in edit mode
        if (mode=="off") {
            currentEditMode="off";
        } else {
            currentEditMode="on";
        }
    }
}

I got all this to work correctly using the Edit button in the row, but I still want to enable clickable rows and have this functionality. I don't want the user to have to click on the edit button to edit the row.

Thanks - so close to the solution!
try
e.Row.Attributes.Add("onclick", "javascript:return checkEditMode('on');" & ClientScript.GetPostBackClientHyperlink(Me.gvMuniData, "Edit$" + e.Row.RowIndex.ToString))
Avatar of CitySec

ASKER

When I tried that it didn't put the row into edit mode, it only performed the checkEditMode function. Anything else you can think of?
could you please paste the view source
Avatar of CitySec

ASKER

Sure:

<tr id="gvMuniData_ctl03" onclick="javascript:return checkEditMode('on');javascript:__doPostBack('gvMuniData','Edit$0')" onmouseover="javascript:ShowPopup('gvMuniData_ctl03_gridPopupNonEdit','gvMuniData_ctl03')" onmouseout="javascript:HidePopup('gvMuniData_ctl03_gridPopupNonEdit','gvMuniData_ctl03','#f0f0f0')" style="background-color:#F0F0F0;">
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
use this javascript, with above script problem with return false

function checkEditMode(mode) {
    if (currentEditMode=="on") {      //there is currently a row in edit mode
        var answer = confirm("You haven't saved your changes to this row. Are you sure you wish to exit?");
        if (answer){          //we are leaving without saving  
            if (mode=="off") {
                currentEditMode="off";
            } else {
                currentEditMode="on";
            }
return true;
        } else {         //we decided not to leave yet
                  return false;
        }
    } else {      //there is not currently a row in edit mode
        if (mode=="off") {
            currentEditMode="off";
        } else {
            currentEditMode="on";
        }
return true;
    }
Hi CitySec
You are going good. Just for the information, Whenever you put return in the javascript function it goes to next function only if the first function returns true.

So make sure every return true if you want to move to the next function.

Harry

PS: Guys I think the function written is bit messy to me have a look into my code.
var currentEditMode="off";
 
function checkEditMode() 
{
    if (currentEditMode=="on") 
    {   //there is currently a row in edit mode
        if (confirm("You haven't saved your changes to this row. Are you sure you wish to exit?"))
        {   //we are leaving without saving  
            currentEditMode="off";
            return true;    
        } 
        else 
        {   //we decided not to leave yet
            return false;
        }
    }
}

Open in new window

Avatar of CitySec

ASKER

I am good with my javascript function. My question still remains as to how to give two javascript functions to one row's onclick event.

This line of code isn't well-formatted:

e.Row.Attributes.Add("onclick", "javascript:if(return checkEditMode('on')){" & ClientScript.GetPostBackClientHyperlink(Me.gvMuniData, "Edit$" + e.Row.RowIndex.ToString) & "}" & )

It should be this instead:

e.Row.Attributes.Add("onclick", "javascript:if(return checkEditMode('on')){" & ClientScript.GetPostBackClientHyperlink(Me.gvMuniData, "Edit$" + e.Row.RowIndex.ToString) & "}")

without the ampersand before the closing parenthesis. And I still don't think this is what I need. To reiterate, I want

1) clicking on a row sends it into edit state
2) clicking on a row checks to see if another row is already in edit state and prompts user if so

I can accomplish each of these requirements solo, but I can't combine the two into one onclick event. How do I do this? How do I add to onclick attributes to a row programmatically?
Avatar of CitySec

ASKER

This line of code: e.Row.Attributes.Add("onclick", "javascript:if(return checkEditMode('on')){" & ClientScript.GetPostBackClientHyperlink(Me.gvMuniData, "Edit$" + e.Row.RowIndex.ToString) & "}")

Causes this Javascript error at runtime:

syntax error

javascript:if(return checkEditMode('on')){javascript:__doPostBack('gvMuniData','Edit$12')}
---------------^
Hi,

Yes,
e.Row.Attributes.Add("onclick", "javascript:if(return checkEditMode('on')){" & ClientScript.GetPostBackClientHyperlink(Me.gvMuniData, "Edit$" + e.Row.RowIndex.ToString) & "}")

so in this case return checkEditMode('on')
when user click first time at that time the grid is not in edit mode then it will not do any thing, but I think at that time also you have to return true for the row event to fire and to set the grid in edit mode and when second time user clicks on the row in which case grid is already in edit mode then it will prompt the user and if user click Ok then it will call the
ClientScript.GetPostBackClientHyperlink(Me.gvMuniData, "Edit$" + e.Row.RowIndex.ToString) & "}") correct

in this case could you please send me code where in when user click on row and it will set the grid in edit mode - or give both aspx and .vb/C# code
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of CitySec

ASKER

That did it. Thanks!