Problem/Motivation

Since #3443833: Provide a way for other modules to flag block plugin implementations as 'navigation safe' introduced a way to add additional types of blocks to be placed in Navigation via Layout Builder, it is now possible to add blocks that contain <form> tags when rendered. This means that after these blocks have been placed and saved, the layout cannot be saved again, because the layout form contains nested <form> tags. This identical problem affected default and override entity layouts in Layout Builder and was fixed in #3045171: Form blocks rendered inside layout builder break save. However, the fix was strictly limited to the entity view display form and the individual entity layout form.

Steps to reproduce

  1. Install Drupal with standard profile
  2. Install navigation module
  3. Create a block that has a form in it, such as a search block or views block with an exposed form
  4. Implement hook_block_alter() in some module and set 'allow_in_navigation' for the block's definition to TRUE.
  5. Log in as administrator
  6. Go to /admin/config/user-interface/navigation-block
  7. Click on the +Add block link
  8. Click the link with the text matching the block's label
  9. Press the Add block button
  10. Press Save and confirm you see a successful "Saved navigation blocks" message
  11. (Optional) Go through similar steps to add any other block, but it's the same without doing it
  12. Press Save
  13. Observe that the warning message "You have unsaved changes." appears no matter how many times you press Save

Proposed resolution

The solution in [##3045171] use a form API #process callback added to the layout_builder element in DefaultsEntityForm and LayoutBuilderWidget, combined with a controller service decorator LayoutBuilderHtmlEntityFormController to move the layout builder element outside the form render array. This works because the layout builder element does not itself set values in form state, but instead interacts with the temp store to save layout data on form submit. However, the #process callback and controller apply only to the the entity form routes for the default entity display and entity layout. The navigation layout form is not a layout form, nor does Drupal\navigation\Form\LayoutForm add the #process callback to the layout builder element.

This is probably best solved by:

  1. Moving the #process callback layoutBuilderElementGetKeys() from the widget and the default display forms to the LayoutBuilder render element
  2. Instead of decorating the entity form controller service, in the LayoutBuilder #process callback, add #pre_render and #post_render callbacks to the containing form render array. In the #pre_render callback, render the layout builder element separate from the form, make sure to collect the cacheable metadata, and save the rendered markup as a non-renderable property. Then the in the #post_render callback, append the layout builder markup to the rendered from markup.

Remaining tasks

Postponed on reproducing a failing test in CI. Investigation: #3494332: Functional Javascript tests are silently skipped on Gitlab CI due to selenium standalone configuration

Test only build fails as expected now.

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

CommentFileSizeAuthor
#6 3493671-square.png123.67 KBplopesc

Issue fork drupal-3493671

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

godotislate created an issue. See original summary.

godotislate’s picture

Status: Active » Needs review
Issue tags: +Needs Review Queue Initiative
Related issues: +#3045171: Form blocks rendered inside layout builder break save

Put up MR 10539, which is ready for review. I'm not sure what's going on with the add tests, since the test-only job passes when it shouldn't. So I also pushed up a Test-only MR, which was failing in the wrong place. Meanwhile the test was consistently failing/passing as expected locally.

plopesc’s picture

StatusFileSize
new123.67 KB

Thank you for noticing this and trying to help Navigation to be more stable. :)

Tested the MR code locally and fixes the issue with the form save process.

While testing it manually, noticed that a new blue rectangle appears on the Navigation Blocks page. See screenshot:

I think it could be easily removed using CSS, but wanted to flag it, just in case it could be an indicator of a possible issue.

godotislate’s picture

Status: Needs review » Needs work

While testing it manually, noticed that a new blue rectangle appears on the Navigation Blocks page.

Oh, interesting. With the LB element moved outside the form, I assume it's picked up some sort of border CSS rule. Will investigate.

godotislate’s picture

Issue summary: View changes
godotislate’s picture

Status: Needs work » Needs review

Added a class to the layout builder element and updated the CSS selector to hide the border.

Not sure what's going on with the test. I think there might be some difference between my local env and Gitlab CI for browser-based tests. I'll look into that later when I have to time to revisit.

godotislate changed the visibility of the branch 3493671-test-only to hidden.

godotislate’s picture

Created separate issue about strange behavior with the browser based tests not running as expected: #3494332: Functional Javascript tests are silently skipped on Gitlab CI due to selenium standalone configuration

godotislate’s picture

Issue summary: View changes

Refactored so that an event subscriber isn't necessary. #pre_render and #post_render callbacks can handle it. Tests pass, but still not getting the test only build to fail as expected in CI, though.

plopesc’s picture

Thank you for pushing this one!

Tested the feature branch manually after the refactor and it is working as expected, solving the reported bug for Navigation & Layout Builder integration. Also tested manually in an entity form and no regressions were noticed.

Added a minor comment in the MR.

Regarding the test only build, not sure if we could go ahead with this one, or some extra work might be needed.

godotislate’s picture

Title: Placing a block containing a form in navigation layout prevents layout builder from saving » [PP-1] Placing a block containing a form in navigation layout prevents layout builder from saving
Issue summary: View changes
Status: Needs review » Postponed

Thanks for the review, @plopesc. I made the suggested change as well as a similar one I forgot.

Not sure what's going on with the test. I created #3494332: Functional Javascript tests are silently skipped on Gitlab CI due to selenium standalone configuration, because I have observed some unexpected behavior going on with the browser-based tests at least, but I've made little headway in identifying the cause. Postponing this issue on the resolving the tests.

godotislate’s picture

Title: [PP-1] Placing a block containing a form in navigation layout prevents layout builder from saving » Placing a block containing a form in navigation layout prevents layout builder from saving
Status: Postponed » Needs review

Tried re-running the test-only job, and it failed as expected! https://git.drupalcode.org/issue/drupal-3493671/-/jobs/3825109.

I'm not sure what's different, but unpostponing and putting back to NR.

godotislate’s picture

Issue summary: View changes

Did a bit of docblock clean up. Test only fails correctly still, so this is ready.

nicxvan’s picture

Status: Needs review » Needs work

Ok this was a doozy to test.

I pulled down 11.x and created a custom module with the block_alter and confirmed the issue occurs, checked this branch out and confirmed it is fixed.

Read through the code a few times, looks good once the two comments are addressed.

godotislate’s picture

Status: Needs work » Needs review

Rebased and updated MR from review.
Test only job still failing as expected.

nicxvan’s picture

Status: Needs review » Reviewed & tested by the community

Comments were addressed, looks great!

quietone’s picture

After reading the issue and MR, I didn't find any unanswered questions. I updated credit.

  • catch committed 38dd1c40 on 11.x
    Issue #3493671 by godotislate, plopesc, nicxvan: Placing a block...
catch’s picture

Status: Reviewed & tested by the community » Fixed

This looks like a really nice clean-up, didn't expect a negative diffstat from the issue title.

Committed/pushed to 11.x, thanks!

Status: Fixed » Closed (fixed)

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