snikch / jquery.dirtyforms

A jQuery Plugin that monitors forms for change and alerts the user before leaving the page.
MIT License
224 stars 55 forks source link

Display Default Dirty Dialog #104

Open vincejairam opened 8 years ago

vincejairam commented 8 years ago

Hi, I using the plugin with http://demos.telerik.com/aspnet-mvc/tabstrip/events kendo tabstrip. I added the onselect event e.g.

` function onTabSelect(e) {

    console.log("Selected: " + $(e.item).find("> .k-link").text());
    if ($('#updateLeadDetailsForm').dirtyForms('isDirty')) {
        console.log("Form is dirty"); //show default dialog
        e.preventDefault();
    }

}`

and the check for if the form is dirty works as expected but I would like to show the default dialog that is registered with the plugin as oppose to creating/launching my own dialog again. I'm currently using the PNotify plugin with dirtyforms.

Any help greatly appreciated.

NightOwl888 commented 8 years ago

Dirty Forms already contains the logic that runs when the user attempts to navigate:

  1. Checks whether any form is dirty
  2. If dirty, shows the dialog and cancels the event that caused navigation
  3. If the user clicks proceed on the dialog, will refire the original event

What you need to do is attach your own event to Dirty Forms so it is possible for it to be cancelled and resumed by Dirty Forms.

$(document).bind('bind.dirtyforms', function (ev, events) {
    var originalBind = events.bind;

    events.bind = function (window, document, data) {
        originalBind(window, document, data);
        $(document).bind('onTabSelect', events.onAnchorClick);
    };
});

// Ensure the above is called before the first call to .dirtyForms()
$('form').dirtyForms();

Now, if you can work out how to get Kendo to throw a document event named onTabSelect with the original DOM event as its first parameter, Dirty Forms can do its work.

If you cannot work that out, then I suggest you attach the event directly to the DOM element that causes the tab to change. Just make sure you attach the event handler to the same element and event that Kendo uses when it detects a tab change.

// Bind additional events to existing handlers
$(document).bind('bind.dirtyforms', function (ev, events) {
        $('#theTabElement').bind('click', events.onAnchorClick);
});

// Ensure the above is called before the first call to .dirtyForms()
$('form').dirtyForms();
vincejairam commented 8 years ago

Thanks for the help, appreciate it.

NightOwl888 commented 8 years ago

Did the above solution resolve your issue?

georgebellos commented 8 years ago

I had a similar setup, multiple forms on tabs. I used the above suggestion on bootstrap tabs

$(document).bind('bind.dirtyforms', function (ev, events) {
    var originalBind = events.bind;

    events.bind = function (window, document, data) {
        originalBind(window, document, data);
        $(document).bind('shown.bs.tab', events.onAnchorClick);
    };
})

but if click cancel it goes to the next tab and if i click leave page it does not reset the form.

georgebellos commented 8 years ago

I also tried the event show.bs.tab still same behaviour.

NightOwl888 commented 8 years ago

Dirty Forms is meant for preventing the user from leaving the page without saving. When a user navigates from one tab to another, they are not leaving the page. In fact, unless you are doing some sort of advanced AJAX, they can navigate back and the data will still be there. So it doesn't usually make a lot of sense to use a Dirty Forms dialog when switching between tabs.

This is the primary reason why Dirty Forms does not manage "form reset" - it doesn't make much sense to do this if the very next action is to navigate from the page. But you could use the proceed.dirtyforms event to do this if you need to.

As for resetting the tab back to the original value, I would suggest using the stay.dirtyforms event.

var previousTab;

$(document).bind('bind.dirtyforms', function (ev, events) {
    var originalBind = events.bind;

    events.bind = function (window, document, data) {
        originalBind(window, document, data);
        $(document).bind('shown.bs.tab', function (ev) {
            previousTab = ev.relatedTarget;
            events.onAnchorClick(ev);
        });
    };
});

$(document).bind('stay.dirtyforms', function () {
    if (previousTab !== undefined) {
        $(previousTab).tab('show');
    }
});

$(document).bind('proceed.dirtyforms', function () {
    // run reset of your tab...
});

So, this is possible, but it is not the default behavior. You need to do some manual work to get there. We can't make so many assumptions about how your application is wired together, or Dirty Forms won't be that useful for the masses.