Problem/Motivation
I can no longer save changes to the layout after any kind of form has been added to the layout.
Steps to reproduce:
1. Enable layout builder on a content type, then open layout builder.
2. Add 'Search Form' block to a section
3. Save the layout
4. Re-open the layout builder, and make some change (e.g. reorder blocks)
5. Attempt to save the layout
The page refreshes, but still shows unsaved changes. At this point, it is no longer possible to save the layout until the search form is removed.
Proposed resolution
Since the layout_builder element is not a form element, and all the layout-related values are managed through the temp store, the layout_builder element can be placed outside the form element, preventing nested <form> tags
- For the
layout_builderrender elements in the layout builder defaults and overrides forms, save the list of array parents to a property ('#layout_builder_element_keys') on the top-level$formelement. - Override/decorate the
controller.entity_formcontroller service. - If the form render array returned from the original service's
getContentResult()method does not have the'#layout_builder_element_keys'property, return the form render array as is. - If the form render array does have have the
'#layout_builder_element_keys'property, then use the property to extract the layout builder element from the form render array and move into a separate render array. Return a render array that has the form and the layout builder element array as sibling child elements.
Remaining tasks
N/A
User interface changes
Layout Builder UI will no longer break when rendering forms
API changes
N/A
Data model changes
N/A
Release notes snippet
Comments
Comment #2
grahamcLooking at the form data posted by the browser, this would normally include
form_build_id,form_idandform_tokenfields, but in this case these are missing...Comment #3
tim.plunkettOh no, that's not good.
Must have broken in #3004536: Move the Layout Builder UI into an entity form for better integration with other content authoring modules and core features.
First step to fixing this is an automated test, tagging for that.
I'd suggest using the User Login form, so we don't have to mess with search.module in our test.
Not sure if it's truly fixable, but in the meantime, here's a workaround to always show a placeholder when a block contains a form.
Comment #6
tim.plunkettMarking #3046667: Can not save override layout if layout contains Form API form that fails validation as a duplicate.
Comment #7
grahamcThe workaround from #3 seems a reasonable compromise, but unfortunately doesn't cover blocks from the Webform module, where I'm hitting the same problem.
(These have a
$content['#type']of'webform', and no child elements)For now I'll be extending the workaround to handle webforms too, but, obviously core shouldn't be name-checking RenderElements from contrib modules, so there ought to be a better solution...
Should Webform have to detect that it's running inside layout builder and avoid outputting forms?
Comment #8
godotislateI had to deal with some blocks containing content with form tags added directly to templates, so my workaround was so swap all rendered
<form>tags with<div>tags. I don't have tests written for this, as I'm not sure it's a great way to deal with the issue.Comment #9
johnwebdev commentedSuper tricky!
This expands (and simplifies the approach from #8) but I'm not sure if it's the right one. Not submitting as patch yet, until we validate if we should actually do it this way.
So basically something like:
would produce:
Comment #10
johnwebdev commentedThis is a failing test. (It passes with code in patch #9 and probably #3) But this wouldn't fail for #7, so we should probably expand this and add a block plugin in a test module that renders a form and probably move this to its own test class with that scenario covered as well.
Not setting to NR.
Comment #11
tim.plunkettRelated issue might help
Comment #12
jwilson3From a technical perspective, #9 seems to be the safer (albeit nuclear) solution, but from an end-user perspective #8 would be more desirable. It would be useful to see a non-functioning preview of the actual form you want to add to the page, so you can decide if it is the right form or not (etc) without having to go through multiple Save changes /=> View page /=> Edit layout /=> Save Changes /=> View page steps.
So then the question becomes how to effectively show a form without visually disabling the components in the form while also ensuring it doesn't interfere with the outer Layout Builder form. The first part is swapping
<form>with<div>like #8 does, but I presume something else would need to be done so that the form elements don't actually submit with the form. Would removing thename=""attributes from all the form elements work?Comment #13
oheller commentedI've applied patch-8 and when I go to edit the layout I get the following errors:
I'm using Drupal core: 8.7.1.
Fatal error: Maximum function nesting level of '256' reached, aborting! in docroot/core/lib/Drupal/Core/TypedData/DataReferenceDefinition.php on line 48.
Fatal error: Maximum function nesting level of '256' reached, aborting! in Unknown on line 0.
Fatal error: Maximum function nesting level of '256' reached, aborting! in vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php on line 65.
Fatal error: Maximum function nesting level of '256' reached, aborting! in /var/www/mndor/docroot/core/includes/bootstrap.inc on line 585.
Comment #14
gnugetI just rerolled #3.
Comment #15
johnwebdev commentedComment #16
yogeshmpawarSetting back to Needs Review & Triggering bots.
Comment #18
tim.plunkettComment #19
rlmumfordThis patch takes a slightly different approach that resolves the issue without having to alter block output.
The patch uses a #pre_render added to the form and a theme hook suggestion to move the layout builder out of the
<form></form>tags.All changes to layouts seem to be made through interactions with the temp-store factory anyway (AFAIK), so nothing from the layout builder element actually needs to be submitted with the form (happy to be corrected on this).
This works a treat for DefaultsEntityForm and OverridesEntityForm out of the box (and doesn't change what users would see at all). If you wanted to display other fields on the OverridesEntityForm then these would always appear above the layout, regardless of weight.
Comment #21
rlmumfordFixed code style and test errors.
Comment #22
ccasals commentedManual testing of #21 results in a layout tab with no content in it. (workflow actions are present but none of the content or sections or LB interface renders.)
Comment #23
rlmumford@ccasals is that with overrides or defaults?
Comment #24
ccasals commented@rlmumford - with overrides. We have a site with existing content, including form blocks, which recreates this issue. The forms are a user login form, a
webformviews exposed filter form, and a custom form plugin. This is NOT a clean install of drupal.Comment #25
ccasals commentedOn further investigation it was the exposed view filter that was causing the issue. Here's an update to #14 that makes it an even bigger hammer. Nested to prevent "undefined index['#type']" errors. That test will still fail, but this at least provides a bandaid for any other sites out there that have content editing blocked by this issue.
Edit for clarity: manual testing of #14 did not resolve the issue. Views form was the culprit.
Comment #27
bnjmnmIn case context is helpful: The test failing in #25 was added in #2973921: Interactive controls inside preview block in the Layout Builder form should be disabled.. This issue disabled interactive elements (including form fields) in Layout Builder preview. The tests included adding a search block to confirm its form elements were disabled.
If the solution to this issue is winds up being the current approach of removing forms entirely, you can address the test failures by removing the parts of
LayoutBuilderDisableInteractionsTestthat refer to the search block (assuming there is test coverage elsewhere that confirming that forms wont even get rendered in preview).Comment #28
mpotter commentedI ran into this issue when embedding several Views blocks into a Layout. The patch in #25 worked and allowed me to save the layout changes. However, the content editors managing the layout were surprised to see the Placeholders for the Views blocks rather than the content.
Wondering if there is a way to still show the block content but not have it affect the Save action. Or at least show Views that do not contain any exposed filters or forms. In my case, the block causing the problem was a Solr search form. But that was only one of several views on the page. I'd be fine if the search form didn't render but the rest did. As it stands this sort of ruins the WYSIWYG-like Layout builder experience people were excited about. And yet this is definitely a major issue that has broken sites that were working with Layout builder prior to 8.7.
Comment #29
ccasals commentedWe were still finding forms that could sneak through. Refactoring the approach in #25 to look more like #8/9 by actually checking for
in rendered content.
The failing test still needs to be updated IF this is an acceptable approach (per points made in #27).
Comment #30
mpotter commentedYes, #29 worked better for me. Normal Views blocks are shown, but not the search form. Layout saves. Nice job!
Comment #31
saseedharan commentedWe were still getting the issue You have unsaved changes On click of Save Layout. I am adding just 2 blocks in the layout a view block and exposed filter block. The version we were using is 8.7.1
Steps to reproduce:
1. Go to any content which uses layout builder.
2. Add any 'view block' to a section.
3. Save the layout. It will be success.
4. Re-open the layout builder.
5. Add any 'Exposed filter block' to the section.
6. Now try to save the layout. You can see You have unsaved changes.
Comment #32
ccasals commentedSimple update to #29 to work with php 7.1.x sites. "count" is not an available method on https://www.php.net/manual/en/class.domnodelist.php prior to 7.2.
Comment #33
phjouI encounter the same bug.
Patch #32 Works for me :)
Comment #34
phjouOk I just updated the patch to use the interface in the dependency injection instead of the class directly.
Comment #35
bnjmnmI discovered a less disruptive solution for the search form while working on #3025231: Concurrent editing of layouts is very confusing.
In
\Drupal\layout_builder\EventSubscriber\BlockComponentRenderArray::onBuildRender()just after $content = $block->build(); I addedWhen #theme_wrappers was present, the Layout Builder form's CSRF token was being rendered outside of the form.
This addresses the inability to save without any UI changes.
It's possible that this only works in combination with other changes made in the issue - I have not tested that. If just the change in onBuildRender() does not fix the issue for search form, check #3025231, which should soon have a patch with that + the other changes that fix the save issue.
Comment #36
ccasals commentedUpdates for unit tests, building on update in #34. The functional js test (LayoutBuilderDisableInteractionsTest) will still fail
Also opened a new issue: https://www.drupal.org/project/drupal/issues/3060656
This is for a longer term better approach that might still allow rendering of forms, if that's possible.
Comment #37
ccasals commentedTriggering the bots to ensure unit tests pass
Comment #41
bnjmnmThis patch is an entirely different approach so there's no interdiff as it's starting from scratch.
With this approach, there is no visible difference with non-views forms, in a render array, it removes the #theme_wrapper key from any item where #type === 'form'
I couldn't do it as cleanly for views blocks with exposed filters since the logic is inside the views executable object. In this case, the views exposed filter form does not render. On the plus side, the rest of the view renders just fine, so it's still a more robust preview than just a label.
Comment #42
sam152 commentedI'm not quite sure that'll work, since I believe required form elements still add validation messages when saving the layout. It might be worth coming up with a few test forms to use as the baseline and for testing whichever chosen solution we go with.
Comment #43
ccasals commentedWould #41 still result in actual nested
<form>..<form>..</form>..</form>? It seems like it would, but maybe I am missing the significance of those theme wrappers.Even if we transform
<form>tags to<div>s, this could still break styles that targeted form elements directly which would be hard to solve for and communicate around I would think.Comment #44
bnjmnmAdded tests that replicate the steps that cause the problem to happen manually, but the tests won't fail. This is not entirely surprising as there are existing tests that also should have failed as they include adding a block with a form and saving a layout.
Fortunately (albeit confusingly), the changes made in #3025231-67: Concurrent editing of layouts is very confusing -- a test-passing patch -- make it so manual and automated testing are consistent. Most likely this patch made it possible to surface these errors in tests because AJAX rebuilds were changed to target the entire entity form instead of just the Layout Builder render element. Based on this, I've attached the following:
BlockComponentRenderArraywhich was added to address the symptoms reported here). The tests now fail as expected.BlockComponentRenderArrayin #41 The tests should pass as expected (running the test again, there was an unrelated fail due to a known media library issue, but the Layout Builder tests pass as expected)BlockComponentRenderArrayin #41. Tests pass because these tests pass without the patch from 3025231...Comment #47
bnjmnmTalked with @tim.plunkett about #44 and we concluded this should be postponed until #3025231: Concurrent editing of layouts is very confusing is completed, as it isn't possible to write test coverage for this issue without it.
In the meantime 3045171--44.patch from #44 should take care of the issue with minimal changes to the Layout Builder UI.
Comment #48
scottsawyerFor what it's worth 3045171--44.patch works great for Drupal 8.7.3.
Comment #49
godotislateI had originally used a workaround similar to #44 in our project, but realized it didn't solve the issue for webforms as mentioned in #7, or other render elements that have
<form>tags in the template.I think behavior I have observed is that such blocks might save in LB the first time they are added to the layout, (though possibly not if the form contains any required fields). However, saving after going back and re-editing the layout subsequently will fail.
Comment #50
scottsawyerGood lord, I just ran into a combination that #44 doesn't address. I have a view with an exposed for in QuickTabs. Those form tags are still present in LayoutBuilder. Not sure how to proceed. I guess I could temporarily disable the exposed filters, update the layout, then re-enable. Let's how we can get #3025231 in quickly :)
Comment #51
mpaler commentedDang. Almost feel like this bug is borderline critical. In my case, if I want to edit a layout with a form(s), I need to remove the forms, make the edits, save -- then re-edit and place the forms again.
Comment #52
tim.plunkett@mpaler is the most recent patch solving your issue
Comment #53
mpaler commented@tim.plunkett -- sadly it's not. I'm on D8.7.3 -- and I have https://www.drupal.org/files/issues/2019-06-19/3045171--44.patch applied. Just tested again. I my case I have a straight up content block with a
inside the block. Trying to save and it never saves, even if i toggle "Show content preview". Removing the block saving a few times (with and without "Show content preview") and the node saves.
FWIW, I also have the following patch applied:
https://www.drupal.org/files/issues/2019-06-18/3053906-11-default-region...
Thanks for all you guys do!
Comment #54
tudxndvn commentedhi all, do you any thing new today?
Comment #55
bnjmnm@mpaler two things would help narrow down why the current fixes are not working for you
Comment #56
mpaler commented@bnjmnm,
3045171-44-with-3025231-67.patch is not applying on 8.7.3 -- even with no other core patches.
Going back to 3045171--44.patch and going to work around for now.
Here's my custom block code in entirety, minus the complete post destination:
Thank you.
Comment #57
gnugetI just want to mention that I'm still using #3 with the modifications mentioned by #7 (I was testing it with a web form) with great results.
It removes the form and displays a text which is not ideal but it lets the UI usable for the user while this is fixed properly :-)
Comment #58
mpaler commented@gnuget -- thanks for the tip. Went that route as we are on a tight timeline. Attached is a re-roll with the webform conditional in case it helps anyone else in a similar crunch.
Comment #59
scottsawyerAny thoughts on how to deal with more deeply nested forms, such as with QuickTabs with Views blocks containing exposed filters? I haven't tested against Block Tabs or related modules, but I am wondering is this patch would address such cases.
Comment #60
tim.plunkett@ccasals had an approach earlier that rendered the HTML and parsed the DOM. I think that's the only bulletproof solution that would also address hand-written forms like the one in #56
That's been split out to #3060656: Explore a better solution for nested forms in Layout Builder
Comment #61
gnugetHi, @scottsawyer.
I think #58 should work for your case as well.
the
containsFormis recursive and it will iterate in all the render array.If somehow the form is already rendered you could try #36 instead which render first the markup and after that check for the
formtag.Comment #62
scottsawyer@gnuget Could not apply #58 to 8.7.3. I have a few other core patches installed, I am going to see if they touch any of the same files.
Comment #63
mpaler commented@scottsawyer -- that was my bad. Please try this one.
Comment #64
scottsawyerOk, that patch applied, thanks for jumping on it.
However, I still get a form tag in my QuickTabs block in layout builder when the QuickTab contains a views block with an exposed form, and still unable to save the layout with the QuickTabs block.
Comment #65
gnuget#36 is the way to go then :-)
I even think that #36 should be committed and any different/better solution should be explored on #3060656: Explore a better solution for nested forms in Layout Builder
Comment #66
scottsawyerWith #36 I am able to save a layout with QuickTabs. Thanks everyone for your efforts.
Comment #67
bnjmnmThis builds off of the approach in #36, but instead of hiding the blocks entirely, it replaces all occurrences of
<form>with<div>. This preserves the UI.Tests were also expanded to cover the hard-coded form use case reported in #53
Comment #68
bkosborneIf you're going to use a regex to perform the replacements, then I suggest not loading into a dom object at all to verify if a form tag exists. I would just use a regex to test if the form element exists as well. Regex is not super reliable for HTML detection and manipulation BTW, since it can take so many different formats. Like
< form>... </ form >.Comment #69
tim.plunkettWe can be reasonably sure that any
<form>tags generated by Drupal will be found here.Any custom code with malformed HTML isn't really something we can be responsible for...
Comment #70
scottsawyerI agree that parsing form tags is hazardous, but it should be rare to have irregular, though not illegal form tags, so unless a better approach is presented, I think this is a 99% solution.
Comment #71
xaqroxHere's a patch using DOM shenanigans to convert the form. Also removed
detokenizeNestedForms()since it did not appear to be in use any longer.Comment #72
philosurfer commented#66 & #71 is not working when we have a block type that inserts a media field (uses media browser in modal).
Comment #73
philosurfer commentedNoting: The patch in #3042190: Creating a block that uses Ajax adds multiple blocks solves the problem for me when we have block types that have media fields.
Comment #74
rlmumford@tim.plunkett (#60) in #21 theres a patch that takes the rendered layout builder out of the form. There was a bug with the overrides, but that approach seems to solve all of the above issues for any form, and renders a realistic preview of the form. Is that not ideal?
Comment #75
bkosbornephilosurfer, can you provide steps to reproduce?
I applied patch from #66. In layout builder, I can add a views block that has exposed form and save just fine. I can also add a custom text block that has a media reference field on it and have no problem selecting a media item from the media browser (both core's media library widget and the entity browser contrib module widget).
Comment #76
bkosborneThe current approaches perform the modifications in
\Drupal\layout_builder\EventSubscriber\BlockComponentRenderArraybut this is not correct and is particularly problematic for the approach in started in #67. This approach performs early rendering of the section render array, and as such prevents other subscribers to the eventLayoutBuilderEvents::SECTION_COMPONENT_BUILD_RENDER_ARRAYfrom acting on the render data. So this breaks contrib (like the Layout Builder Styles module).Instead, the early rendering and form replacement could be done in
SectionComponent::toRenderArray(), after all event subscribers have finished.But even then, it seems dangerous to do this early rendering, since layout templates may want to modify the render data and will no longer be able to.
I wonder - is a pure JavaScript solution a possibility? Why can't we swap the
<form>tag with a<div>using JS?Comment #77
coderbrandon commentedI've rerolled/downrolled the patch from #71 (without tests) so that it can apply to 8.7.1, if it helps anyone else.
Comment #78
chs commentedConfirmed in 8.7.5 version build with webform version 5.1.0 build, not available any save both - multilingual and single language,
any possibility to roll patch with backport to previous version?
regards,
Mike
Comment #79
rlmumfordRe-roll of patch in #21.
Comment #80
renatog commented#77 works good on 8.7.5 using Webform w/ Layout Builder
Comment #81
ccasals commentedHi all,
This came up recently in conversation so I figured I would clarify here: there are multiple approaches to patching this problem in this issue thread! If you are just looking to patch your site, please patch carefully.
Moving latest to oldest:
Patch thread ending in #79 (started from #21): this approach take the entire layout builder form out of rendering, then re-adds it using a preprocess hook. Has not been tested by the community yet.
Patch thread ending in #77 (builds on #71, #66, #44, #41): this approach renders each block before placing it in the form and if it finds
<form>elements it converts them to divs. It will work on any block with a form in it (no matter how deeply nested). This means that forms will probably look right, but are mutated html while in the Layout Builder preview. This has been reviewed and tested by the community and bypasses the problem.Patch thread ending in #63 (builds on 58): this approach looks for content with #type set to 'form'. If it is set to form, it uses the "placeholder for [block name]" functionality to prevent break. This will work for many types of forms, but there are cases where it won't catch nested forms (aka, in a view block with filter). YMMV
Patch thread ending in #36 (builds on 34, 32, 28, 25, 14, 3): this approach renders the block content, looks for a
<form>element. If it finds a form in the block, it uses the "placeholder for [block name]" functionality to prevent break. It will work on any block with a form in it (no matter how deeply nested). This has been reviewed and tested by the community and bypasses the problem.I think at this point, we need to make a decision on which of these approaches is best on balance, and doesn't impact things like accessibility (I have concerns about malforming semantic forms to look like divs, for instance. I think assistive technologies will probably choke on this.) Every approach has a tradeoff though, so we're going to need to pick which one is least problematic.
Comment #82
batkor#77 Works for my. TY
@ccasals Anyway need remove or replace child tags
Comment #83
muaz7731+1 for patch #77
Comment #84
kris77 commentedpatch #77 work for me too.
Comment #85
renatog commentedI'm checking and #77 really works well for a lot of members.
I applied the patch, tested and it works here as well.
Updating status for RTBC.
Thank you, guys.
Comment #86
renatog commentedComment #87
bkosborneSorry, but I do not think this is a viable solution. I understand it's working for many people, but the forced early rendering - particularly where it's being done - would prevent some contrib modules from working. See my comment in #76
Comment #88
bnjmnmRe-adding the "Needs tests" tag as the patch that has tests does not appear to be the one people are in favor of.
This issue can't be considered RTBC without a test that replicates the error when unpatched, and has no errors when it is patched
Comment #90
rohit tiwari commentedHi,
Applying patch #77 gives me below error,
`ArgumentCountError: Too few arguments to function Drupal\layout_builder\EventSubscriber\BlockComponentRenderArray::__construct(), 1 passed in /var/www/globalcms/docroot/core/lib/Drupal/Component/DependencyInjection/Container.php on line 269 and exactly 2 expected in Drupal\layout_builder\EventSubscriber\BlockComponentRenderArray->__construct() (line 52 of core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php).`
In our case we are following below steps,
1) We are adding embed form in block.
2) Add the block through layout builder.
3) Able to save the layout.
4) Edit and make any other change and hit save.
5) Unable to save with message `You have unsaved changes`
Comment #91
murz@Rohit Tiwari, clearing Drupal cache after applying patch should fix this error.
Comment #92
gerzenstl commentedPatch submitted in #79 works well.
I'm using Drupal 8.7.8.
Comment #93
mirom commented@bkosborne none of the approaches from #81 is working for your usecase? #63 seems to be doing the same thing as you describe.
Comment #94
bkosborneHi mirom, my concerns with the approach taken in #77 is outlined in my comment #76. To recap, my issue is that it forces early rendering of the block component before other event subscribers have a chance to alter the render data. This early rendering is performed even if there is no form present in the data.
Contrib that has event subscribers to this block component render event will not have a chance to act on the render data in a meaningful way. For example, the Layout Builder Styles module subscribes to this same event to add CSS classes and template hints to the block. That cannot happen now because the render data has been converted to just #markup with HTML already rendered.
The solution is to do this form replacement in a different area, after the event subscribers have all run.
Comment #95
tim.plunkettWhat about an additional event subscriber that is set with -1000 priority that performs this rendering?
Comment #96
bkosborneCan't it just go in SectionComponent::toRenderArray() after all the subscribers are done?
Comment #97
tim.plunkettA couple reasons.
Comment #98
bkosborneOk, that makes sense.
I suggest also that the code be modified so that it doesn't perform the early rendering if there is no form found. Right now it's updating the render data by reference. I think it should clone the render data first, and then if a form is found replace the original. That reduces the side effects this may have.
Comment #99
a3hill commentedBuilding upon #77 so items that don't have forms, don't render the content as part of this process and therefore skipping theme preprocessing and templates. In my case, after using patch #77 it fixed the save issue as advertised but disrupted the display of existing themed blocks.
Comment #100
batkor#99 Works for my.
Thank guys
Comment #101
johanf commented#77 works fine and #99 works fine too . Thanks
But still a problem ... The form has to be the only block in the section.
If i add the form and a view in the same section i get this 'you have unsaved changes' again
Comment #102
bkosborneHere's the same code as #99, but it's moved to a separate event subscriber with a very low priority. This resolves my original concern.
I cannot reproduce the problem from #101. I added several blocks to the section, including several form blocks, and I was able to save the layout. Can you provide more detailed steps to reproduce?
Comment #103
bkosborneEmpty file uploaded by accident... Those Gitlab integrations can't come soon enough...
Comment #104
cameron prince commentedI was seeing the same as #101, but switching to the new patch in #103 allowed me to save the node. In my case, I was embedding two product entities via the WYSIWYG in two custom blocks added in the same section. The products render inside an add to cart form.
Comment #105
shimpyI have tested patch #103. It works for me. I have added the layout builder in one of the content type and tried managing the content layout. I added search form block or any form entity or node block , it is saving the layout but if I make changes in the block it is showing me unsaved changes tag even after clicking on save layout.
But later i applied the patch #103 it is save the layout without showing the unsaved changes tag.
Comment #106
sam152 commentedHi @shimpy, this issue still has the "needs tests" tag, so it should be marked as "Needs review" or "Needs work" until those are done.
Comment #107
rensingh99 commentedHi,
I have checked the patch and it worked as design.
Below are my updates.
1). I have enabled the layout builder for the "basic page" content type.
2). I have added a search form using a layout builder. After that, I was not able to save the layout for a basic page.
3). I was able to save the layout after applying the patch.
4). Also, I have added a view in the same section below the search form and it saved successfully.
There was one error as per the Drupal coding standard. I have fixed it and uploaded the patch with interdiff.
Thanks,
Ren
Comment #110
kualeeI have tested the patch provided in #107. It applied cleanly and worked as expected.
Here is my test usecase:
- Patch tested on a fresh install of Drupal 8.9 with webform module enabled.
- I conducted testing on basic page content type, adding a few different form elements (either one form at a time or in a few different combination)
The patch worked as designed in all different combination of content.
Cheers
Comment #111
sam152 commented@kualee, unfortunately the patch still needs tests. NW for those.
Comment #112
kualee@Sam152 ah sorry I have just re-read your comment in #106. Would you be able to provide some guideline/point me to the direction to work on the automated test? Really keen to get this issue RTBC but I have never contributed anything so not sure where to start. Thanks!
Comment #113
jwilson3Hi @kualee,
The documentation to get started on writing tests for core issues is here
https://www.drupal.org/contributor-tasks/write-tests
Without looking too deeply into it, I'd suggest scouring the Drupal 8.9 source code for examples of tests that relate to Layout Builder and possibly tests that relate to event subscribers to get an idea of how tests are being written elsewhere in core.
Comment #114
damontgomery commented#71 has tests if you want a starting point for adding one to #103.
And, thanks for the work everyone.
Comment #115
aangel commented#105 worked for me, thank you everyone.
Spotted a spelling error. $orginal_content should be $original_content.
Comment #116
shimpy#107 worked for me. I have corrected the spelling as per #115. Please Review.
Comment #117
cobenash#116 worked for me.
Thanks.
Comment #118
tim.plunkettPlease remove these unrelated changes.
Wrong docblock
Changes
Converts
I think this also needs an empty post_update hook to allow the new service to be discovered after updating. See layout_builder.post_update.php for examples.
Finally, this still needs tests
Comment #119
Madhura BK commentedComment #120
Madhura BK commentedHave implemented changes suggested in #118.
Comment #121
meenakshig commentedComment #122
tim.plunkettChanges in #120 are fine, but this still needs tests.
Comment #123
kris77 commentedPatch in #120 works fine for me.
Comment #124
godotislateHere is a failing test. 3 different types of blocks are added to both default and overrides layouts:
I think these three should provide comprehensive (if not redundant) coverage of blocks containing forms.
It seems that the initial adding of the blocks and saving may succeed, it's just after subsequent editing of the layout with the blocks already in place, it's not possible to save (or discard or revert).
Comment #125
pavel ruban commenteddeleted*
Comment #126
rlmumfordI still think the approach outlined in #120 is misguided. It changes the POST data submitted when someone clicks the save button. If there are buttons in the form blocks, clicking them will have the effect of submitting the form.
For example, if any of the forms in the blocks contain a button with the name "Discard Changes", clicking it accidentally or otherwise will result in the layout changes being discarded.
Any form input in the block forms will still be submitted when the layout form is submitted - this just seems wrong. I'm guessing that means that a form_build_id will be submitted for every form displayed in the layout.
Taking the layout out of the form entirely is a better way to go, as it ensures that only the expected data is being submitted when you click "Save Layout" and "Discard Changes". It also stops any submit buttons in the layout blocks having any effect on the layout form. This is the process outlined in #79 and #21.
Comment #127
rlmumfordReroll of #79 with a test. The test uses the user login form, but i don't know if that will render because the user will be logged in. The search form might be a better fit.
Comment #129
rlmumfordMoved the pre render callback into a class for security.
Comment #131
rlmumfordComment #132
godotislateI like the idea in #131 of rendering the layout builder element outside the form. I have an alternate approach to do that by decorating the entity form controller service so that a new theme entry isn't required.
But first, a fix/update to the tests in #124
Comment #134
godotislatePatch with fix and tests.
Comment #135
godotislateRealized logic in the controller could be simplified.
Comment #136
godotislateProbably better to delay moving the layout builder element outside the form render array at least until after the form is built.
Comment #137
alvarito75 commentedThe patch in #136 works amazingly for me.
Comment #138
kualee+1 RTBC
I have tested the patch in #136 and it worked for all of the scenarios that I tested
- Webform
- Comment form
- Views with exposed filter
Tested with either one form at a time or combination of a few
Awesome work @godotislate
And thanks @jwilson3 @damontgomery for the suggestion, I ended up never finding the time to get around to do it :(
Maybe someone could review the source code? I only performed all the tests, not reviewing the actual code. I will leave this as needs review for now
Comment #139
tim.plunkettThis is soooo close now! Just a couple small things. But I think the approach is inspired, and I'm excited to see it work out so cleanly
👏🏻👏🏻👏🏻
Nit: missing a blank line here
Bad copy/paste here
FormBuilderInterface
The plugin ID for the plugin instance.
(there's another issue about fixing it where you copied it from)
Can this be done with
starkinstead?Comment #140
godotislateThanks for the review! Updated patch per comments.
Comment #141
tim.plunkettNice, I didn't even notice this, thanks for fixing.
#140 addresses all my feedback, RTBC
Comment #142
kualee+1 RTBC
Might be a bit overkill, but I have just retested all the scenarios I did in my previous test with patch #140 applied.
Comment #143
tim.plunkett@kualee in this case, it was overkill because the last set of changes were only to documentation and some tests. But it's good practice and a good habit anyway, and I appreciate your thoroughness! Thanks!
Comment #144
rlmumford@godotislate thanks for taking that approach and running with it! Some really good improvements and I'm looking forward to this getting committed!
Comment #145
renatog commentedI was using #77, today I tested with #140 and really works well here.
+1 to #RTBC
Comment #146
johnwebdev commentedThis looks amazing! +1 RTBC.
Comment #147
rhovland+1 RTBC Works very well on a layout with several embedded views blocks with 50+ forms inside them
Comment #148
acbramley commentedNice! Patch #140 fixed an issue we were still seeing while using #103 with a custom block that was posting to mailchimp. Thanks!
Comment #149
sam152 commentedConfirming this patch also worked great on a site I maintain, was able to delete a lot of custom code that emptied forms out on layout builder pages.
One note on the implementation, you could avoid overriding
controller.entity_formby specifying a custom_controllerfor just the layout builder form route that required this fix.As I'm writing this, I've realised if the layout builder widget found itself on other entity forms somehow, the fix would then fail to be applied, so not sure it's actually an improvement. +1 RTBC.
Comment #150
godotislateDoes anyone think it's worth moving
layoutBuilderElementGetKeys()to a trait?Comment #152
tim.plunkettTestbot fluke (The "https://packages.drupal.org/8/drupal/provider-2019-3%249934973132b9718f8..." file could not be downloaded)
I don't think the two identical one-liner static methods warrant a trait.
Comment #153
batkorThanks you so much guys!
#140 is working. Drupal 8.8.1
Comment #154
alexpottBefore committing this it'd be great if someone could update the issue summary to reflect the current solution because it doesn't.
This looks like really nice work and a great test.
Comment #155
godotislateComment #156
godotislateComment #157
godotislateIS updated.
Comment #158
alexpott@godotislate thank you for the issue summary update.
Committed and pushed 0a16b0f112 to 9.0.x and 87bdfdfc49 to 8.9.x. Thanks!
Can we get a follow-up to replace these with:
I fixed the file mode on commit.
Comment #163
alexpottThis broke the D9 build (obvs and oops) - test modules no longer need to declare a core version. I hotfixed this.
Comment #164
catchIf this is only to rebuild the container, it doesn't need an empty post-update - since the container cache key includes Drupal::VERSION
If it's to clear caches too then we do need it.
Comment #165
rfletcher73 commentedI am using Drupal 8.8.2, can i install this patch from #140 to my Drupal install? I noticed on the patch page it says it is for 8.9.x branch.
Comment #166
damienmckennaJust to mention it, #140 applies cleanly against 8.8.x, is there any chance this could be committed there too? Thank you.
@rfletcher73: Yes, you could use patch #140 against your 8.8.x codebase.
Comment #167
rfletcher73 commentedThank you. I am having problem installing it on my local drupal build for testing.
I originally installed Drupal with Composer so i think i should use Composer to install the patch file too.
I've updated my composer.json file by adding this block under extra: {..}
Then from the command prompt, i am running composer install. I am getting response back in the tmerinal, but it is not installing the patch. What am i doing wrong here?
Comment #168
damienmckenna@rfletcher73: The composer.json file's "patches" item should refer to the package that the patch is applied to, which is "drupal/core" and not "drupal/layout_builder", e.g.:
Comment #169
rfletcher73 commentedThat is what I had at first, but when i ran composer install, it didnt pull the patch in. So, i guessed Layout Builder being a module needed the module way of updating packages. I guessed wrong. :)
I changed it back to drupal/core. I also updated the package information to match what you have, but I think that doesn't have any effect on it, its just there to describe what the patch does. Is that right?
With those changes, when i ran composer install, it worked!!! My first patch applied to Drupal. Thank you!!!
Comment #170
damienmckennaCould a release manager please review whether this could be backported to 8.8.x? It affects production sites today (which is how I came across it). Thank you.
Comment #171
tim.plunkettI think it would need a new patch that combines in the hotfix from #163
Comment #172
damienmckennaThe patch still applies cleanly to 8.8.x and (in my personal testing) resolves the problem, moving back to RTBC.
Comment #173
rajab natshahUsing the 3045171-140.patch with 8.8.x-dev
Comment #174
dimilias commentedThe patch from #140 also solves our case and our form consists of all sorts of types of fields when the issue was occurring, dependent fields, custom fields, computed fields, inline entity forms, comment fields etc. +1 to RTBC.
Comment #175
thetaPCPatch #140 works great with core 8.8.4. Thanks!!!
Comment #176
nguyenphanI got this problem when use layout builder and block webforms.
It is good with patch #140 (core 8.8.4).
Thanks a lot.
Comment #177
dubs commentedSame for me - #140 works a charm - thank you for everyone's work on this :-)
Comment #178
andrimont commentedThank you @godotislate and all for the patch.
On Drupal 8.8.4, the #140 worked for saving the basic page.
Still I keep having (since Drupal 8.8.3) a symptomn : the webform block doesn't show up on a basic page. I am not sure if it is related.@nguyen.phan, do you see this issue ?
EDIT : In fact, the webform block is fine. There is no trouble now ;-)
The issue was that the setting Allow each content item to have its layout customized was not set anymore. This went unseen because the layout of the basic page still could be customised.
Comment #179
anybodyConfirming RTBC for #140 on 8.8.x, thank you all very much!
Comment #180
mizage@gmail.com commented#140 worked me. Thanks!
Comment #181
catchDiscussed this with xjm, and neither of us are very keen on backporting this to 8.8 (new post update, new service etc.), running the patch against 8.8 is of course viable, and it's not too long before 8.9.0 gets a release candidate.
Moving this back to fixed against 8.9.x
Comment #182
jaykandariComment #183
geek-merlinGreat stuff!
The new LayoutBuilderHtmlEntityFormController does not comply with decoration contract though, causing a regression.
Comment #184
neelaj82 commentedHi all,
The #140 patch got applied to our version 8.8.4 but the layout builder is not saving still. We are using an exposed form filter view inside the layout builder. If i remove the view from the page then I can save it.
Update: Cache clear was needed after the patch. working now!!
Comment #186
xjmAs per #181.
Comment #187
dave reidOne thing to note about not backporting to 8.8, is that install profiles using composer-patches have no way to conditionally apply patches to specific older versions of projects, which then requires individual sites to manually add the patches-ignore section. Just something to consider for bug fixes, but I get the hesitation about why not to backport this issue.
Comment #188
chucksimply commentedWas this applied to the 8.9 production release a few days ago?
Comment #189
jsibley commentedExactly. Production 8.9
Comment #190
chrisckThank you for the work on this patch. I ran into this issue today with Drupal 9.0.7 trying to display a search filter in layout builder. I see that it was committed to 9.0.x. Does anyone know when this would be pushed to a D9 stable release?
Comment #191
antiphon commentedThis issue has not been fixed in 9.x. I just encountered it with 9.1.4.
Comment #192
oleh.tarasiuk commentedYes, I have the same on 9.2.0, I think issue should be reopened.
need restore section storage from tempstore to resolve it.
Comment #193
rskleven commentedI can confirm this is still an issue in 9.3.3.
Comment #194
larowlan@rskleven this was fixed in Drupal 8.
If you've got a similar issue in D9, its a different problem - can you please open a new issue with the details of your scenario?
Comment #195
wunaidage commentedencountered this issue on drupal 9.4.5
Comment #196
bnjmnmTo reinforce what @larowlan said in #194 - commenting that you're having a problem a closed issue is not going to result in anything getting fixed. Two year old issues aren't reopened, especially one that automated test coverage objectively proved to have fixed some issues.
It looks like some people are experiencing additional bugs and if those were reported in a new issue something could actually be done about it. Details on how to reproduce the issue or providing a failing test would be necessary, too. The The steps to reproduce in this specific issue no longer cause an issue. It's certainly possible there's a use case that was not accounted for that could be fixed, but "I'm still getting the problem in (version)" is not enough to go on.
If you're just commenting to vent, vent away. If you're hoping a comment here will result in a fix, it won't. There needs to be a new issue reporting the bug, and there needs to be specific steps on how to reproduce the problem.
Comment #197
kavya n n commentedRe-rolling the patch for 10.3.X
Comment #198
jwineichen commented#197 worked for me
Comment #199
davidwhthomas commentedJust noting, I had the same issue with a views exposed form inside the layout builder layout.
On save, nothing except "op" was submitted and nothing was saved.
The attached patch in #197 fixed the issue for me too, in Drupal 11.2.x