Problem/Motivation
Layout Builder misbehaves with new extra fields. New pseudo-fields cannot be removed, InvalidArgumentException thrown
Steps to reproduce
- Do a standard site install
- Enable Layout Builder
- Set Article content type to "Use Layout Builder" by checking the box on Manage Display and saving.
- Enable a module that adds a visible extra field. For example this sandbox project: Extra Field Example
- Clear cache
- Go to manage the Layout at /admin/structure/types/manage/article/display/default/layout
- Attempt to remove the new extra field block by using the contextually link
- See the ajax operation fail with a
InvalidArgumentException: Invalid UUID in Drupal\layout_builder\Section->getComponent() (line 177 of web/core/modules/layout_builder/src/Section.php).
Proposed resolution
Current work-around is to first save the layout with the new field present. I suppose that generates a UUID for that new pseudo-field. Edit the layout again and you can remove the field.
A real fix would involve getting the section storage into the tempstore more quickly. In 9.1.x that happens in the PrepareLayout EventSubscriber. Prior to 9.1.x, that would happen in the prepareLayout function in Drupal\layout_builder\Element\LayoutBuilder.
Remaining tasks
The current patch does not address 9.0.x or 8.9.x. Those may be out of scope, depending on how "major" this bug is considered.
User interface changes
None
API changes
None
Data model changes
None
Comment | File | Size | Author |
---|---|---|---|
#28 | interdiff_24-28.txt | 4.29 KB | danflanagan8 |
#28 | 3144010--28.patch | 5.54 KB | danflanagan8 |
#27 | interdiff_24-27.txt | 406 bytes | ravi.shankar |
#27 | 3144010-27.patch | 5.62 KB | ravi.shankar |
#24 | interdiff_18-24.txt | 674 bytes | danflanagan8 |
Comments
Comment #2
cilefen CreditAttribution: cilefen commentedExceptions that can be easily thrown by UI actions are major priority.
Comment #3
Sivaji_Ganesh_Jojodae CreditAttribution: Sivaji_Ganesh_Jojodae as a volunteer and commentedIf you can attach an example module with
hook_entity_extra_field_info()
andhook_entity_view()
it would be handy to test the issue.Comment #5
danflanagan8I was able to reproduce following the steps in the description. I did a Standard site install. Then I set the default view mode of Article content type to display with Layout Builder.
Then I added the code below to the core telephone module for convenience, enabled telephone, and cleared cache. I went to the Article layout and tried to remove the Test Pseudofield. I saw the same error in the console relating to invalid UUID.
Comment #6
tim.plunkettGreat, thanks for that. I was able to reproduce.
In the short-term, here's the very silly workaround:
Once you save the layout (including the extra field), you can then remove it.
It's only during the time that it is *not yet saved* that this can break.
Which is because it is being dynamically added in
\Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay::setComponent()
, with a fresh call to\Drupal::service('uuid')->generate()/code> on every page.
Which means the UUID is one thing when the UI is printed (with the link to remove or configure), and another UUID by the time the form is loaded to remove/configure it.
This is still a very annoying bug (and an embarrassing one as the person who wrote the code) but since it has a straightforward workaround I'm downgrading to major.
The next step is to write tests that expose the bug.
Comment #7
danflanagan8Here's a patch that adds a new test to LayoutBuilderUiTest (FunctionalJavascript) that covers this issue. The new test is called testNewExtraFieldRemoval().
This function includes a couple of commented lines that recreate the current workaround. Uncommenting these lines results in the test passing. Not sure if that will help us, but it's in there.
Comment #8
tim.plunkettComment #10
danflanagan8I *think* this patch does the trick. Fingers crossed on the tests. This patch also resolves #3069578: Layout builder doesn't show new "extra fields" I think, which I've added as a related issue. I cross posted the patch so it gets visibility there.
I'm not great at git so here's a copy/past interdiff!
Comment #11
danflanagan8Yes! It passed! The "idea" of the patch is that it looks like we need to get the section storage into the tempstore as soon as possible.
I noticed that to work around the bug you don't even need to save the layout, which is the workaround described in the issue summary. It's sufficient to do any action on the form that results in the section storage getting added to tempstore, like moving any block or removing any block. After taking such an action you can do whatever you want with the buggy extra field block.
Comment #12
samiullah CreditAttribution: samiullah at Salsa Digital commentedLooks good
If further code review is not needed, this can be moved to RTBC
Comment #13
tim.plunkettI'm closing #3069578: Layout builder doesn't show new "extra fields" as a duplicate, because this issue is further along. It's still not 100% clear to me why this change fixes the bug from the other issue, but it does... And it is clear why it fixes this one.
Can't see from the patch context, but this means an extra set() even when it's already there.
Currently we have an if/elseif, and no else. The if case does not need this set(), but the elseif and unwritten else case do.
Let's switch to only having an if/else, make the current elseif a standalone if inside the else, and have the set() call at the end of that else. (hope that makes sense)
Also add an inline comment explaining that we're adding it to tempstore regardless of what the storage is.
Replace this with the actual cache needing clearing:
\Drupal::service('entity_field.manager')->clearCachedFieldDefinitions();
Let's remove this
Might as well finish removing it, just to prove the whole process works
Comment #14
danflanagan8Thanks @tim.plunkett. All those notes look good. I have some free time now so I can make those changes.
Regarding #3069578: Layout builder doesn't show new "extra fields", do you think we should include a test addressing that specific situation? It would be easy enough to add a second extra field that has
visible => FALSE
. It wouldn't even have to be a whole new function. It could just be a few lines added to the test we're already working on here.Comment #15
tim.plunkettYes please!
And can you expand the issue summary here to include that?
Thanks
Comment #16
sorlov CreditAttribution: sorlov at Skilld commentedI have tried to check issue from https://www.drupal.org/project/drupal/issues/3069578 with patch #10, but have no success.
Extra field with
visible => FALSE
is not shown in LB.Same problem, if you have
visible => TRUE
, but then disable layout_builder, move the extra_field to "Disabled" and then re-enable layout_builder.While patch #21 from original issue solves the problem, so I'm not sure that it should be closed as duplicate.
Comment #17
danflanagan8You're right, @sorlov. I'll re-open that issue (#3069578: Layout builder doesn't show new "extra fields") and comment there.
Thanks for testing. Sorry for the confusion I caused!
Comment #18
danflanagan8Here's a patch incorporating all the feedback from comment #13.
And as @sorlov pointed out, I was mistaken that this also fixed #3069578: Layout builder doesn't show new "extra fields". So this patch does not increase the scope at all; my ambition in #14 was misguided!
Comment #19
danflanagan8Comment #20
danflanagan8Removing "Needs issue summary update" tag. That was added based on my confusion regarding the connection to #3069578: Layout builder doesn't show new "extra fields".
Comment #22
danflanagan8Updating the issue summary.
Comment #23
tim.plunkettWe usually don't reference issues like this, that info can be gotten from the git log/blame
Otherwise I think this is ready to go!
Comment #24
danflanagan8Here's a new patch with that small change to the test description.
Comment #25
tim.plunkettThanks!
Comment #26
catchLooks really good but some cspell issues - either needs the words splitting or added to the dictionary:
Comment #27
ravi.shankar CreditAttribution: ravi.shankar at OpenSense Labs commentedAddressed comment #26, added extrafield and fieldlayout into dictionary.
Comment #28
danflanagan8If extrafield isn't already in the dictionary, there's no reason to add it for this. I should have put a space in that from the beginning. Here's a new patch that changes extrafield to extra_field. There's no way around adding fieldlayout to the dictionary since it comes from a programmatically created css class.
If reviewers prefer #27 though, that's fine.
Comment #29
tim.plunkett#28 looks good to me, thanks!
Comment #31
andypostSend retest as it failed
Comment #34
catchSplitting rather than adding to cspell makes sense to me as well.
Committed/pushed to 9.2.x and cherry-picked to 9.1.x, thanks!
Comment #36
heddnThis seems to have caused regression #3207875: "Unsaved changes" message incorrectly appears on layout builder.