Ajax behaviour on entity edit form action buttons can break

Created on 16 February 2023, almost 2 years ago
Updated 9 June 2024, 6 months ago

Problem/Motivation

On entity edit forms, the action buttons are moved into a new group gin_actions receive new ids in /js/edit_form.js. This can break ajax behaviours that might be attached to them, because those work based on the element id (drupalSettings.ajax).
This seems to be a race condition relating to the order in which the attached libraries are called. I was able to isolate the issue to a situation where it works if the drupal.contextual-links is loaded (contextual module enabled and user has permission to use contextual links) and it fails if the library is not loaded. If that library is present, it also loads the core/drupal.ajax library before the edit_form library, which makes the ajax system process the action buttons before GIN changes the IDs. If the contextual links library is not present, the core ajax library is loaded after GIN makes these changes with the result that the ajax behaviours for the action buttons do not work.

Steps to reproduce

- Install Drupal with the default profile (drush site-install)
- Enable GIN and set it as the admin theme (drush then gin && drush config-set system.theme admin gin -y)
- Create a custom module , e.g. gin_demo with this content for the module file:

/**
 * Implements hook_form_FORM_ID_alter().
 */
function gin_demo_form_node_form_alter(&$form, FormStateInterface $form_state) {
  // Change the behavior of the preview button to show a message instead.
  $form['actions']['preview']['#ajax'] = [
    'callback' => 'gin_demo_form_node_form_preview_callback',
    'event' => 'click',
  ];
}

/**
 * Form submission handler for the 'preview' action.
 *
 * @param array $form
 *   An associative array containing the structure of the form.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   The current state of the form.
 */
function gin_demo_form_node_form_preview_callback(array $form, FormStateInterface $form_state) {
  $response = new AjaxResponse();
  $response->addCommand(new AlertCommand('Do you see this?'));
  return $response;
}

- Enable that module (drush en gin_demo
- Login in as user 1, create a content of type article, save, and go to the edit form
- Click preview and confirm that a JS alert appears
- Uninstall the Contextual module (drush pm-uninstall contextual)
- Go to the same edit form again, click preview and confirm that the JS alert does not appear and the preview page opens

Proposed resolution

If the change to the element ids is necessary, ajax instances assigned to them should be notified/updated.
I'm not an expert on the client side implementation of the ajax subsystem, but I have a patch that seems to reliably fix this issue in all situations where I encountered it (2 to be honest).
It also seems to be fixable by adding core/drupal.ajax as a dependency for the gin/edit_form library, though not sure how much sense that makes conceptionally.

Remaining tasks

Fix, review, test.

πŸ› Bug report
Status

Closed: outdated

Version

3.0

Component

Code

Created by

πŸ‡©πŸ‡ͺGermany berliner

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @berliner
  • Status changed to Needs review almost 2 years ago
  • πŸ‡©πŸ‡ͺGermany berliner

    This patch fixes it for me.

  • πŸ‡©πŸ‡ͺGermany berliner

    That was too quick and not properly tested. This one is fixing the issue for me.

  • πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica

    Confirming this issue. We're running into it when changing layout paragraphs sometimes.

    This was also confirmed in πŸ› Problem with form submit button's not working after an ajax call would refresh the form-id Closed: duplicate (was closed as duplicate of this).

  • πŸ‡¨πŸ‡­Switzerland saschaeggi Zurich

    @Anybody can you rest if the patch fixes the issue for you?

  • πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica

    @saschaeggi the problem is, that the issue only appears from time to time, so there's no reliable way to test it. Even if it works, it doesn't mean it does in general. So I think we need to ensure that in theory.

  • πŸ‡©πŸ‡ͺGermany berliner

    @Anybody The steps to reproduce from the issue description don't help you isolate the problem? It took me a while, but in the end I was able to reliably reproduce this issue in my setup.

  • πŸ‡¦πŸ‡ΉAustria hudri Austria

    This is a little bit similar to issue 3387363 πŸ› z-index problem with media library widget Closed: works as designed : Ajax requests can break if the dependency declaration of libs is missing or conflicting (e.g. through duplication). In this case there is a conditional (Ajax), but undefined dependency of gin/edit_form on drupal.ajax.

    In response to #7:
    The problem is reproduceable, but you have to check if a library is included on page load, or added later through an Ajax request.

    I think berliner's approach is a quite clever approach, which avoids unconditionally adding the drupal.ajax library on all forms.

    OTOH, I wonder if the change of the button's id is really necessary? Doing a code search on the Gin folder, I can't see --gin-edit-form being used anywhere (except being created initially). Maybe we can refactor edit_form.js instead and remove the manipulation of the ID.

  • Status changed to Needs work about 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States sim_1

    Patch #3 did not work for me. However patch #23 from the duplicate issue πŸ› Problem with form submit button's not working after an ajax call would refresh the form-id Closed: duplicate did work for me. Using that instead.

  • πŸ‡΅πŸ‡ΉPortugal rfmarcelino

    Reroll #23 (and #15) from #3276752

  • πŸ‡©πŸ‡ͺGermany berliner

    Rerolled #3 for rc9.

    I would be in favour of not changing the ids in the first place though, just as hudri suggested. Removing unnecessary complexity is always preferable.

  • Assigned to Grevil
  • πŸ‡©πŸ‡ͺGermany Grevil

    Going to move using an issue fork instead of patches. Still unsure, which patch to use as a foundation. I'll start with the original from @berliner.

  • Pipeline finished with Failed
    11 months ago
    Total: 361s
    #87817
  • Issue was unassigned.
  • Status changed to Postponed: needs info 11 months ago
  • πŸ‡©πŸ‡ͺGermany Grevil

    The patch by @berliner (now applied to the current MR) fixes the issue described in "Steps to reproduce"!! Unfortunately, the issue I had locally, has not much to-do with the AJAX integration (I thought it would, but instead it seems to be caused by custom client code).

    Nevertheless, we should get this issue fixed.

    @sim_1, what exactly did not work for you? Were you testing the patch through the "Steps to reproduce"? Or do you have another example where the current Patch / MR doesn't fix the issue? Please give us more information.

    LGTM! But setting to "postponed" regarding #10.

  • πŸ‡ΊπŸ‡ΈUnited States sim_1

    Ok, i'm doing my best to remember... I wish I'd written down more details when it was fresh. I wasn't following the reproduction steps exactly. I was also working with custom client code:
    - a custom module
    - in the .module file there is a form alter that adds two widgets, and then attaches an ajax callback to each.
    - admin theme is gin

    I believe then I was getting ajax errors in the console when trying to use the submit buttons. It wasn't all the time, only after ajax had been triggered on the form by using either of the fields with callbacks. I can try to go back and reproduce. But I am guessing that all I meant by the patch not working is that it didn't fix my particular issue (not the exact repo steps from this description), but the other patch did.

  • Status changed to Needs review 11 months ago
  • πŸ‡©πŸ‡ͺGermany Grevil

    Thanks for the clarification @sim_1! This definitely sounds like the patch doesn't work as intended, if you got the time, feel free to reproduce it using the current MR! Otherwise, we should check both patches and see if we can find a middle ground between them. :)

  • πŸ‡΅πŸ‡ΉPortugal rfmarcelino

    The patch in #11 had a typo where sticky was called out of scope.
    Here's the fixed patch.

    I tried to apply #12 instead and I'm unable to submit the form after ajax runs.
    With this patch, it works.

  • Still not working for me. Changing something in layout_paragraphs still causes this issue randomly.

    Created a Quickfix for this, using position: sticky and flexbox to have basically the same experience (while it doesn't look that perfect, but it works).

  • πŸ‡©πŸ‡ͺGermany berliner

    I get the feeling that this get's a bit out of hand here.
    Those last patches do not seem to address the original issue about the changed button ids and the outdated references in the ajax subsystem. #12 should fix the issue as demonstrated by the "steps to reproduce", so this should be reviewed and tested. The other patches seem to be about different issues. Maybe it would be better to create a new issue for those with sufficient information to reliably reproduce the problems and then fixing them.

  • Status changed to Closed: outdated 6 months ago
  • πŸ‡¨πŸ‡­Switzerland saschaeggi Zurich

    This will be fixed with ✨ Move Action buttons to sticky header Fixed

Production build 0.71.5 2024