- Issue created by @fathershawn
- First commit to issue fork.
- πΊπΈUnited States fathershawn New York
Posting some notes and code snippets from conversations in Slack. I'm not using the issue fork as we aren't really ready for that yet as there are still dependencies that need to be committed.
I loaded up the 11.x branch locally and spent more time stepping through
FormBuilder
,FormAjaxResponseBuilder::buildResponse
, andFormAjaxSubscriber::onException
with xdebug.- The form is definitely cached on an ajax interaction. This happens at
FormBuilder.php:436
- I reversed the actual effect of
FormAjaxSubscriber::onException
. The Ajax classes copy the new build ID back to the form.
So I removed the previous code to maintain build_id from my POC branch and instead added the following immediately after the
$form['form_build_id']
part of the form is built inFormBuilder::prepareForm
.// If a form is building from an HTMX request and the form id has changed // add htmx attributes to update the build ID in the client. // @see \Drupal\Core\Form\EventSubscriber\FormAjaxSubscriber::onException // @see Drupal.AjaxCommands.update_build_id if ($this->isHtmxRequest() && $form['#build_id'] !== $input['form_build_id']) { $existing_id = Html::getId($input['form_build_id']); $htmx_attributes = new HtmxAttribute(); $htmx_attributes->swapOob('outerHTML:input[data-drupal-selector="' . $existing_id . '"]'); $form['form_build_id']['#attributes'] = AttributeHelper::mergeCollections($form['form_build_id']['#attributes'], $htmx_attributes); }
We don't have all the similar tools available yet, but this would be adding
data-hx-swap-oob='outerHTML:input[data-drupal-selector="existing-form-build-id"]'
to the build id input element on the response.And that works! Validation is working, form_build_id is changing.
- The form is definitely cached on an ajax interaction. This happens at
- First commit to issue fork.
- π«π·France nod_ Lille
we need π Return htmx responses as SimplePageVariant Active before this works properly
- πΊπΈUnited States fathershawn New York
I pushed up a draft MR of how I imagine this implementation. I've commented out a condition that would depend on the upstream issue, but otherwise the single export form works here. My experience is that the form builder out of band swap needs to be deeper in the build process to prevent the validation error.
Nice edge case catch on the nested case with a full form swap @nod_!
- π«π·France nod_ Lille
very nice. I couldn't make the config export form work on my end. I have no idea why setting the data-hx-swap-oob earlier makes the whole thing work⦠There is a side effect somewhere and couldn't figure out what it is yet.
I think the changes to the form are a bit worrying. We can't expect people to make this kind of changes to switch from ajax to htmx. I guess that's a concern for once things actually work.
Just realized we're going to have troubles with inline form errors, we need to swap the whole wrapping element, not just the select when it's updated.
- πΊπΈUnited States fathershawn New York
I think the changes to the form are a bit worrying. We can't expect people to make this kind of changes to switch from ajax to htmx. I guess that's a concern for once things actually work.
Maybe someone will see how to turn the ajax callbacks into process callbacks? I haven't experimented with that at all. Since this form is pure ajax, the form building logic was definitely distributed into the callbacks.
Just realized we're going to have troubles with inline form errors, we need to swap the whole wrapping element, not just the select when it's updated.
Switched to the
js-form-item
classes. Were data attributes not a thing when those were added to our markup? - πΊπΈUnited States fathershawn New York
I looked over @nod_ latest update and our approach in FormBuilder is now very similar:
- I have helper methods to check the request if it's from HTMX and to check for the HTMX trigger value which also makes our code differ in a few places but we are checking the same things.
- We approached targeting the build_id element differently. nod_ adds an id - I go with the existing input[name="form_build_id"][value="' . $old_build_id . '"]' selector for the build id element.
- I extend elementTriggeredScriptedSubmission using the detected trigger from HTMX since any element type can be the trigger.
Our adaptations to
\Drupal\config\Form\ConfigSingleExportForm
are very different, so I'll speak for what I am trying to accomplish. I want the code to be explicit, and to show the full htmx paradigm of request, select, target, swap.I also have a helper method on
FormBase
to determine which element triggered the request. - πΊπΈUnited States fathershawn New York
Nice changes from @nod_ that take advantage of existing workflows for FormBuilder. Pulled those into my branch and we are now more closely aligned:
We still approach targeting the build_id element differently. nod_ adds an id - I go with the
drupal data selector
pattern.I also have a helper method on FormBase to determine which element triggered the form build. As I noted in #13 our approaches to refactoring
\Drupal\config\Form\ConfigSingleExportForm
are different. I use the helper method to detect and respond to which element caused changes. My intention is to be explicit so some future developer (myself included!) sees the dynamic flow. It also allows me to use the HTMX push url attribute to update the url when a config value is actually exported. - π«π·France nod_ Lille
it's not actually postponed.
Looks like the only big difference is the configexport form, which probably shouldn't be part of this issue so we can discuss the approach on how to htmx-ify the forms without holding up the necessary pieces in this MR
The Needs Review Queue Bot β tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide β to find step-by-step guides for working with issues.
- π«π·France nod_ Lille
Opened a MR with only the changes we converged on, I kept the swap-oob true, I could be convinced to do it like before but I don't want to keep track of css selectors in the backend.
Added a small condition so that form_build_id doesn't get the htmx attribute when its not an htmx request.
- πΊπΈUnited States fathershawn New York
I kept the swap-oob true, I could be convinced to do it like before but I don't want to keep track of css selectors in the backend.
This is a fine place to use that since the #id is reliable here. I offered the selector as a way to make fewer changes to the class.
- πΊπΈUnited States fathershawn New York
Matching the priority to π DX object to collect and manage HTMX behaviors Active as the new functionality in that issue will not work in forms without the changes in this issue.
- πΊπΈUnited States fathershawn New York
The MR that prompted the move away from RTBC is hidden in the issue. Returning to RTBC after leaving a comment pointing to the final MR.
- π¬π§United Kingdom catch
Argh OK, so the MR looks a lot simpler, but now there's no test coverage or conversion?
- πΊπΈUnited States fathershawn New York
@nod_ and I had different ideas about how to convert the
ConfigSingleExportForm
form I've been using as an example.My understanding is that he converted it so that all three form elements were replaced on every response so that any changes that were caused by changing a value were updated in the form. Based on comments above he is demonstrating how easily convert a form.
I wanted to demonstrate the request/select/target/swap process that is so common in HTMX usage. My solution had more code that was conditional based on which select element triggered the change.
I think we both see merit in the other's approach but he decided to defer the conversation. If you would like to see the example and test @catch, we should try to reach consensus on the approach.
- πΊπΈUnited States fathershawn New York
@catch I brought our consensus changes to FormBuilder over to the MR 12942 and improved my test. I'd welcome your guidance on how to proceed with this issue.
- π«π·France nod_ Lille
We should move the changes to the config form in a new issue like we have for π Ajaxify the user interface translation forms Active so that we can use the new Htmx object so that we can start using the helper.