Look at the more_actions.js file, specifically the updateFormId() function.

        const formId = form.getAttribute('id');
 [...]
              document.querySelector(`[data-drupal-selector="${formId}"] [data-drupal-selector="${buttonId}"]`).click();
 [...]

The code assumes, that formId and data-drupal-selector are identical. Which they initially are.
However, after an Ajax triggered reload, they diverge.

In our local example, form #id and data-drupal-selector initially are "node-document-edit-form"

After Ajax, they are "node-document-edit-form--4fZYYVW-UEc" and "node-document-edit-form-4fZYYVW-UEc" respectively. Note the "--" vs "-" before the random String.

Under the hood, this in FormBuilder.php and Html::getUniqueId($unprocessed_id); vs Html::getId($element['#id'])

The former creates a "--", the latter reduces it to "-".

So, the code needs to either query by ID instead of data-drupal-selector, or get the selector by ID first, and then use that next.

Issue fork gin-3503304

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

christianadamski created an issue. See original summary.

saschaeggi’s picture

Status: Active » Postponed (maintainer needs more info)

As you reported this as being an issue on rc15, can you reproduce this issue on either stable release 3.0 or 4.0.2?

I'm pretty confident that we've fixed this in rc16+

christianadamski’s picture

Status: Postponed (maintainer needs more info) » Needs work

This is current 4.0.x:

https://git.drupalcode.org/project/gin/-/blob/4.0.x/js/more_actions.js?r...

formId is still directly used as selector for data-drupal-selector.

christianadamski’s picture

Want me to write an MR? If yes, what approach would you prefer?

So, the code needs to either query by ID instead of data-drupal-selector, or get the selector by ID first, and then use that next.

saschaeggi’s picture

Yes, feel free to spin up a MR with a fix and adding steps how we can reproduce it!

The id is being used which generally would be correct as it gets updated by the context object in an Ajax request running through Drupal behaviors. In my short testing with an simple Ajax form this seems to work as expected and the id gets replaced with each Ajax call. But maybe your user case does not run through this function somehow.

I've also quickly did spin up an vanilla instance on tugboat here: https://master-oipts4sjqrrbzlm2ezjy0rvvw0jnjxkj.tugboatqa.com/admin/stru...

(admin/admin) and if you change the "Allowed number of values" it sends an Ajax request and the id gets changed, Save gets the updated form id and form selector id.

Cheers!

christianadamski’s picture

StatusFileSize
new15.26 KB

Well, perfect example actually. See attached Screenshot of the tugboat install.

form ID and data-drupal-selector diverge after AJAX call. So the more-actions.js code does not apply anymore.

It seems however, that it is simply not executed here?

saschaeggi’s picture

Thanks for the clarification! Yes, this seems to be wrong.

Why the use case I was testing still works as expected: For that button to function correctly, the important part is what gets set on the submit button themselves. The form attribute is referring to the id of the form and the data-gin-sticky-form-selector is referring to the the action being triggered (also an id). This seems to be correctly set. As this button doesn't have to rely on the additional click() event from JS as it can directly (natively) trigger the id which is defined in the form attribute on the button (that's an native HTML feature). That's why this still works as expected.

So in a nutshell, if that's not the case for a form action the JS never gets triggered in the first place because of the id and data-drupal-selector selector mismatch.

If you can spin up an MR which changes the part within the if (buttonSelector) {} to use [id="${formId}"] instead of [data-drupal-selector="${formId}"] this should be fixed.

We might want to additionally exit the function when the form attribute exists (and is a valid attribute) on the action and is available in the dom, but this could be done in a follow-up.

christianadamski’s picture

For which version? 4.0.x? And then run webpack dev? Anyway, tomorrow...

christianadamski’s picture

Version: 8.x-3.0-rc15 » 4.0.x-dev

christianadamski’s picture

Status: Needs work » Needs review

I tested locally with 3.0-rc15 and transferred the changes manually. So didn't technically test 4.x, but the code is identical, so should be the same.

saschaeggi’s picture

Hey @christianadamski thanks for creating an MR, I left one comment 👀

christianadamski’s picture

Ok, good to go I guess.

volkerk made their first commit to this issue’s fork.

volkerk’s picture

Use once to add eventlistener for button sync. Added mousedown event in case of ajax buttons, see #3499408: custom ajax button not working anymore

volkerk’s picture

miha.wagner’s picture

Status: Needs review » Reviewed & tested by the community

I can confirm that the patch with the addition of Volker's change restores AJAX button functionality.

saschaeggi’s picture

@christianadamski can you confirm that the latest added changes still work in your case? Thank you

jurgenhaas’s picture

RTBC +1

saschaeggi’s picture

Status: Reviewed & tested by the community » Fixed

Thanks! 👏

Released & included in 4.0.3

https://www.drupal.org/project/gin/releases/4.0.3

Status: Fixed » Closed (fixed)

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