Updated: Comment #0

Problem/Motivation

#2055853: [meta] Improve the place block UX; Separate interaction from the create block UX; Improve the existing blocks-by-theme layout includes putting the "Place block" form into a modal.
However, when you add the code to make a link trigger a modal, the form will not submit.
And if you hack the submit button to submit, then the modal will not close.

And if you do those two things properly, your form will no longer work in a non-modal context.

Proposed resolution

Make forms reusable as modal forms, improve DX of modal-ifying a form.

Remaining tasks

Find the way to do that.

User interface changes

N/A

API changes

None yet

#2055853: [meta] Improve the place block UX; Separate interaction from the create block UX; Improve the existing blocks-by-theme layout

CommentFileSizeAuthor
#5 dialog-2057725-5.patch697 bytestim.plunkett
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

larowlan’s picture

Looks like prepareDialogButtons in core/misc/dialog.ajax.js is the issue here so that went in with #1879120: Use Drupal-specific image and link plugins — use core dialogs rather than CKEditor dialogs, containing alterable Drupal forms from memory.
If I add

return;

to the start of that function, we get back our standard submit handler.
I've stepped through the code (you need to add debugger; at the start of the function (instead of return;) to get the debugger to work with chrome (and you might need to add //@ sourceURL=dialog.ajax.js to the top of your file depending on your version - it looks as though the event listener is attaching to proxy the dialog submit to the original submit button but it ain't working, nothing is triggered.
But it doesn't work.
To test
enable ajax_test
head to ajax-test/dialog
Click the 'entity form' link
Try and save the contact category

Javascript and tests don't play nice do they :(

nod_’s picture

Issue tags: +JavaScript

The patch will touch a javascript file, tagging accordingly. Please remember to tag "JavaScript" so that JS maintainers are able to review JS patches and avoid situations like #2057371: Re-Replace all $.each() with filtered for loop. Thanks.

Wim Leers’s picture

#1: You'll want to pull in quicksketch for this, since he wrote core/misc/dialog.ajax.js's Drupal.behaviors.dialog.prepareDialogButtons(). I'm not familiar with all the Dialog subtleties.

jessebeach’s picture

Issue tags: +Spark

Adding Spark tag.

tim.plunkett’s picture

Status: Active » Needs review
FileSize
697 bytes

This is the offending code. I'm not sure of the repercussions of this change, but I know it works.

There are two e.preventDefault(); in prepareDialogButtons, and they seem redundant. One assigns forces the new button to trigger the original button, the second one (which I've deleted) is responding to submit.dialogSubmit, whatever that is.
But I tested the image add modal, the config sync modal, and the ajax-test/dialog for contact categories.

The contact one does not work in HEAD, but works with this patch.

quicksketch’s picture

One assigns forces the new button to trigger the original button, the second one (which I've deleted) is responding to submit.dialogSubmit, whatever that is.

.on('submit.dialogSubmit') is the same thing as just saying .on('submit'), the ".dialogSubmit" part is a namespacing for the binding so you can remove it individually if needed.

I'm not sure this code is needed any more. Previously it was in place to ensure that using the enter key to submit the form would click the first button. However then we switched to the 0 width/height/padding/border approach (http://mattsnider.com/how-forms-submit-when-pressing-enter/) instead of hiding the buttons with display: none.

I remember having some specific problems around keeping the dialog-behaviors working after a validation error occurred within a dialog. After commenting-out/removing this code, can you try to use the WYSIWYG dialog for inserting an image, but leave the URL empty? That should throw a validation error. Then try inserting a URL and making sure that the form still operates properly after the failed validation. If that particular problem doesn't come back with this code removed, I think it indicates this is left-over cruft from a previous attempt at getting the enter-key to behave correctly.

tim.plunkett’s picture

I tried that, both in HEAD and with this patch it just inserts a broken image. No validation is triggered.

When testing the contact category modal in HEAD, nothing happens. With this patch, a validation error takes me to the form's actual URL, leaving the modal.

tim.plunkett’s picture

Oh, there is no validation to fire in the image dialog :)

When I added validation to core/modules/editor/lib/Drupal/editor/Form/EditorImageDialog.php, it fired just fine, with and without this patch.

So we should be okay here.

tim.plunkett’s picture

Title: Regular forms cannot be reused as modal forms » Regular forms cannot be submitted when used as modal forms
larowlan’s picture

Status: Needs review » Reviewed & tested by the community

Validation works as expected, there is no functionality (without building #ajax into your form) for validation to return to the modal, it should redirect to the form's #action by default.
In light of that, rtbc

nod_’s picture

Nice find, I'm good with it.

Less code++

quicksketch’s picture

Validation works as expected, there is no functionality (without building #ajax into your form) for validation to return to the modal, it should redirect to the form's #action by default.

Hi guys, just making sure I'm understanding this correctly. In the case of the editor image dialog:
- The Image dialog should have the URL field required.
- When you submit the form but it's empty, it should display the validation message, "The URL field is required" inside the dialog after AJAX submission fails, without page reloading or redirecting.

But for a *normal* form displayed in a dialog, that's right, there is no built-in ability to display validation inside the dialog. It must be done by adding an #ajax behavior to your form. A form in a dialog is just a form in a dialog right now, so special auto-ajax is added. Submission and validation must be manually added via #ajax if you want to keep the dialog open.

jessebeach’s picture

I don't understand why we'd remove the detach callback

-    detach: function (context, settings) {
-      $(context).find('form').off('submit.dialogSubmit');
-    },
jessebeach’s picture

nod_ points out that this patch removes the only instance of submit.dialogSubmit, so the detach callback isn't needed any more either.

Tested and it's good to go.

tim.plunkett’s picture

@quicksketch, in my testing, Chrome performs its own validation first. When I add explicit FAPI-based validation, it behaves as expected.

EDIT: So yes, what you said is correct, and we might have a normal follow-up for exploring making this easier or automated (taken from EditorImageDialog):

      // No regular submit-handler. This form only works via JavaScript.
      '#submit' => array(),
      '#ajax' => array(
        'callback' => array($this, 'submitForm'),
        'event' => 'click',
      ),
quicksketch’s picture

When I add explicit FAPI-based validation, it behaves as expected.

Great. RTBC +1. Sorry for the cruft in the original patch. :)

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Yay less code! :)

Committed and pushed to 8.x. Thanks!

Automatically closed -- issue fixed for 2 weeks with no activity.