Rails 3 form helper to prevent user from navigating away and losing changes?
Asked Answered
O

1

6

Is there a Rails helper or a Rails way of preventing the user from leaving the current page if they're typed something into the form on the current page?

I'm trying to prevent people from losing data if they click a header link if they have unsaved changes in a form.

Oreste answered 23/2, 2011 at 7:29 Comment(0)
D
2

Rails doesn't know about the state of a form until it is submitted, but you can add a pinch of javascript to help in that case.

$('#header > a').click(function(){
  $('input').each(function(i){
    if ( $(this).attr(value) != '' ) {
      if ( confirm('are you sure you want to leave this form unfinished?') != 'true' ) {
        alert('quitter!);
      }
    }
  });
});

edit: Okay, so that only handles header link clicking (like you specified in your question), here's a solution that uses onbeforeunload. Full page source because I tested it out to make sure I'm giving you something to build on:

<html>
  <head>
    <title>Foo</title>
    <script>
      window.onbeforeunload = function(){
        var inputs = document.getElementsByTagName('input');
        var unfinished = 'false';
        for (var i=0; i<inputs.length; ++i) {
          if ( inputs[i].value != '' ) {
            unfinished = 'true';
          }
        }
        if ( unfinished == 'true' ) {
          return 'Are you sure you want to leave?';
        }
      }
    </script>
  </head>
  <body>
    <form>
      <input name='foo'/>
      <input type='submit'/>
    </form>
    <a href='/'>Leave</a>
  </body>
</html>

Of course this isn't a Rails-specific helper, but you could write your own helper to spit out a script tag with something like this in it into your views. You'll probably also want to put form-specific checks in rather than just checking every input for emptyness. Every form I've ever made was a beautiful and unique snowflake in some form or another.

Disquiet answered 17/3, 2011 at 3:11 Comment(4)
I suppose, but that doesn't use anything in Rails. Plus that doesn't account for clicking other things like buttons. I was looking for a more elegant solution like in the form tag helper of specifying that you want Rails to generate some JavaScript code to prevent early page unloads.Oreste
@Oreste Rails 3 uses UJS and depends on a JavaScript driver like this one to provide specific functionality. Rails no longer actually generates any JavaScript code from its helpers. The closest thing to what you're looking for is to pass another attribute to the form, like <form data-prevent-change-loss="true"> and use some JavaScript to find forms with that attribute set and then use Unixmonkey's solution on it.Sipes
Does this code have to be added to the header tag? I was going to implement this only into the edit and new views that had to do with my blog posts and product descriptions since I have a newsletter form on pretty much every page that I didn't want to have affected by this. Thanks!Conroy
@Conroy No, it doesn't necessarily need to be in the header, although if someone were to visit your page, fill in something and quickly click a link before that javascript finishes loading, then that javascript won't be executed. Your JS would have to be pretty slow for that (though it is possible), but in my opinion, that would be an edge case I wouldn't worry about. You are improving the experience in the majority of cases, and using default browser behavior for those that move freakishly fast.Disquiet

© 2022 - 2024 — McMap. All rights reserved.