-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Perform template synchronisation in the InnerBlocks component #11681
Comments
I have exactly the same problem when setting a custom template for the 'post' post type. My template has the same template locking setup. |
I have the same problem with the same setup. |
Yes, I think nested templates validation should not happen at the root level like it's done now but it should happen inside the |
Is there a workaround for this issue? |
You can manually force the template validity by dispatching a dispatch( 'core/block-editor' ).setTemplateValidity( true ); |
This bit me today as well. I solved it with the trick @mmtr shared; here's my full code if anyone wants to steal it: /**
* WordPress dependencies
*/
import { compose } from '@wordpress/compose';
import { withDispatch } from '@wordpress/data';
import { InnerBlocks } from '@wordpress/editor';
/**
* Container block
*
* @return {Object}
*/
const Editor = () => (
<InnerBlocks templateLock={ false } />
);
// This is a hack which forces the template to appear valid.
// See https://github.com/WordPress/gutenberg/issues/11681
const enforceTemplateValidity = withDispatch( ( dispatch, props ) => {
dispatch( 'core/block-editor' ).setTemplateValidity( true );
} );
export default compose(
enforceTemplateValidity,
)( Editor ); Definitely feels hacky though; I'd love to see it resolved in a better way :) |
This is VERY much a hack around WordPress/gutenberg#11681 Previously, it was fine to do this just once at the beginning. But we discovered that it also happens when performing undo. Granted, performing undo might do something else, but my best guess is that it's related to the above issue.
@chrisvanpatten Does your fix also work when using the Columns block in the InnerBlocks? That's when I still get the error—other blocks seem to work fine. EDIT: For context, this is how I'm registering the block. The underlying motivation is having a CPT template where some blocks are fixed and unchangeable, followed by this empty block where users can add anything they want (since the Group block isn't in core yet). const { compose } = wp.compose;
const { __ } = wp.i18n;
const { withDispatch } = wp.data;
const { registerBlockType } = wp.blocks;
const { InnerBlocks } = wp.editor;
registerBlockType('vo/empty-block', {
title: __('Empty Block'),
icon: {
src: 'media-spreadsheet'
},
category: 'common',
supports: {
inserter: false,
reusable: false,
html: false
},
// This is a hack which forces the template to appear valid.
// See https://github.com/WordPress/gutenberg/issues/11681
edit: withDispatch(dispatch => {
dispatch('core/block-editor').setTemplateValidity(true);
})(() => <InnerBlocks templateLock={false} renderAppender={() => <InnerBlocks.ButtonBlockAppender />} />),
save: props => {
return <InnerBlocks.Content />;
}
}); |
This is VERY much a hack around WordPress/gutenberg#11681 Previously, it was fine to do this just once at the beginning. But we discovered that it also happens when performing undo. Granted, performing undo might do something else, but my best guess is that it's related to the above issue.
According to GitHub, @mmtr @noahtallen and @getdave (all from Automattic) have touched commits that work around this issue by suppressing the warning. @chrisvanpatten is a Gutenberg core team member and provided a similar workaround posted above. Please tell me someone is officially working to fix the root cause. Otherwise, we might as well remove the warning entirely. 😞 Edit: I'm sorry to call people out, but it seems like there's smart, capable people here on this issue that has been languishing for almost a year. I believe in you and am rooting for you. |
Thanks for calling us out! I mean it! Speaking for my own project, we were trying to ship a fix quickly which is why we didn't focus on this side of things. I think I'll have some extra cycles in the next week or two and I'll try to poke around at this. |
@jrchamp I agree completely that this is an important issue which needs to be solved. I think it's also a relatively complicated one; the "fix" above is really a hack, and not something that should be integrated into Gutenberg itself. Prep for WordPress 5.3 has definitely taken priority for much of the core team, but I'll try to bring this ticket up in an upcoming Gutenberg meeting, and I'd encourage you to join as well (9am Eastern time in #core-editor in WordPress Slack). |
In an episode of terrible lazyness, until this is fixed or I learn exactly how withDispatch works, I'm using the following, less-subtle hack (SCSS->CSS enqueued by admin_enqueue_scripts) – hey, it will probably encourage me to think of a better solution every-time I see the modified warning.
|
cc @youknowriad I started diving into this issue and was curious if you could give a bit more guidance. Here's what I found poking around the current code:
As mentioned, this architecture results in this bug, since it doesn't allow for different locks to apply to different levels. Global template validation in the editor provider currently has no concept that individual blocks could have their own template and rules for the template.
I'm trying to figure out what this would look like. In So InnerBlocks is already validating the template it gets through props separately from the global template. So a way to fix this bug would be to not continue recursing in validateBlocksToTemplate if we reach a block which does its own validation. However, the current implementation would not provide a way to do this - in that function, the block data does not contain information about its own template, using InnerBlocks, or having a template lock. I would greatly appreciate some guidance if folks have some ideas of what they'd like to see happen :) |
Yeah, this seems like the crux of the problem. Potentially, we could a block API to define the behavior but it doesn't seem perfect as the behavior could change from one instance to another of the same block type. I wonder if we could do something like:
I'll also ping @jorgefilipecosta he's the expert here :) |
I wonder how this should integrate with the InnerBlocks template. So I can say |
@noahtallen Good question, I think the prop should have priority in these cases if the template locking is explicitely set as a prop to innerBlocks. |
Hi all, thank you for the explorations on this issue 👍 @noahtallen, @youknowriad To me, it seems the solution to this problem is not to continue recursing in validateBlocksToTemplate at all. Let's only validate if the top-level blocks match. Then if descendent blocks have a locking, their validation mechanics will trigger. If they don't have locking, we can see that specific inner block area as a not locked and a controlled part where the user is free. |
yeah, that's exactly what I was suggesting as well. |
This approach would be very straight forward :) One thing I'm curious about, though. In the docs we specify that nested blocks in the templates are viable to support container blocks. do we not support that case any more, or is there somewhere else where we need to add validation to replace what was happening with the recursion? Thanks for the tips, btw, it's very helpful to understand the context :) |
@noahtallen Nice summary and I think you got everything right.
This is indeed the most difficult problem, we already have a helper that does this "somehow" (the sync mechanism), we can use some of it or make it more flexible. Also maybe instead of having a selector/function to retrive the global template per clientId, maybe a simpler way is to instead provide that template as we render the tree using a prop/context: basically while looping through the blocks in BlockList, also loop through the global template and make the sub-template available to the sub block. |
This continues to be a big frustration point for us, considering all of our content types contain top-level template locking. Dispatching an event to "force" the template to be valid is such a messy hack. I'm curious if there are any small action items that we can do to move this forward? I'm open to seeing if I can find some time sponsorship as well to address. |
I would suggest to bring up this issue during the Open Floor of a Core Editor Meeting. To create some discussion around it. |
For what it's worth, I think some of our FSE/edit-site investigations in this PR might help us solve this issue as well: #21368. |
Is there a workaround for this validation issue for server-side blocks? Or is |
Yes, you should be able to access it like this as long as you are in the editor JS context: window.wp.data.dispatch( 'core/block-editor' ).setTemplateValidity( true ); |
Hi @john-freedman and others who have commented in this thread. |
I just came across this myself and have tested it with WP 5.7 and this is still an issue. |
I can confirm it still is an issue, and I think one side-effect of this bug could be related to the issue where blocks with Another side effect seems to be that you cannot insert patterns in innerblocks with |
It sounds like we just need a person to work on this issue. |
I can't tell if I'm running into the same bug or a different one, but I'll mention it here first since it feels very similar but is with I have an Accordion Block and an Accordion Content Block. Both use Here are the respective /* Accordion Block */
const AccordionTemplate = [
[ 'core/heading', { placeholder: 'Accordion Title' } ],
[ [ 'mrw/accordion-content' ] ],
];
export default function Edit() {
return (
<div
{ ...useBlockProps( {
className: 'mrw-accordion',
} ) }
>
<InnerBlocks
template={ AccordionTemplate }
templateLock="all"
/>
</div>
);
} /* Accordion Content Block */
const AccordionContentTemplate = [
[ 'core/paragraph', { placeholder: 'Accordion Content' } ]
];
export default function Edit() {
return (
<div className="mrw-accordion__content">
<InnerBlocks
template={ AccordionContentTemplate }
templateLock={false}
/>
</div>
);
} Like I said, I can save the block fully if I remove |
I am still encountering this issue on Wordpress version 6.0. I use ACF nested blocks and this error occurs when I change anything about the blocks involved, even things that should not invalidate the template. |
@talldan Dan I am pinging you about this issue as I believe it might be something you want to know about. |
I was directed here by support of the WP Job Manager plugin. I'm running into this same issue while using their plugin, across multiple sites. They don't have a solution at this time, but I thought it might be useful info for this thread. Let me know how else I can assist. I did create a video for them of the actions to replicate if that is helpful: [https://www.loom.com/share/80d7c1cada5942c3be75315dfc236bf8] |
To add to @daisymae6580 's comment above, WP Job Manager jobs are CPTs. |
Has there been any progress on this issue over the past year? I still encounter the same problems as others mention. I have a number of page templates for different post types: import {
useBlockProps,
RichText,
InnerBlocks,
ButtonBlockAppender,
} from "@wordpress/block-editor";
import "./editor.scss";
import { AllowedSections } from "../../Settings.js";
export default function edit({ clientId, attributes, setAttributes }) {
return (
<div {...useBlockProps()}>
<InnerBlocks
allowedBlocks={AllowedSections}
templateLock={false}
renderAppender={() => (
<ButtonBlockAppender
className="section-appender-button"
rootClientId={clientId}
/>
)}
/>
</div>
);
} However they are used, we almost always end up with the warning: "The content of your post doesn’t match the template assigned to your post type.". It can at best be suppressed until the page is next loaded. foreach ($templates as $template => $postTypes) {
foreach ($postTypes as $postType) {
$post_type_object = get_post_type_object($postType);
$post_type_object->template = [
[$template, []],
];
$post_type_object->template_lock = 'all';
}
} I am a bit of a dinosaur and I am struggling to even make the workaround work. If I modify my edit.js file to the following: import {
useBlockProps,
RichText,
InnerBlocks,
ButtonBlockAppender,
} from "@wordpress/block-editor";
import { compose } from "@wordpress/compose";
import { withDispatch } from "@wordpress/data";
import "./editor.scss";
import { AllowedSections } from "../../Settings.js";
const Editor = ({ clientId, attributes, setAttributes }) => {
return (
<div {...useBlockProps()}>
<InnerBlocks
allowedBlocks={AllowedSections}
templateLock={false}
renderAppender={() => (
<ButtonBlockAppender
className="section-appender-button"
rootClientId={clientId}
/>
)}
/>
</div>
);
};
const enforceTemplateValidity = withDispatch((dispatch, props) => {
dispatch("core/block-editor").setTemplateValidity(true);
});
export default compose([enforceTemplateValidity])(Editor); Then I the browser shows: This block has encountered an error and cannot be previewed. And the console shows: Which seems impossible to debug. |
2023 update, with the select + dispatch context providers you can now turn off block validation like this: import { useDispatch } from '@wordpress/data';
import { useEffect } from '@wordpress/element';
/* However you register your blocks.... */
export default {
name: `test/block-name`,
...
edit: (props) => {
// Call the context provider
const { setTemplateValidity } = useDispatch( 'core/editor' );
// Turn validation off
useEffect(() => {
setTemplateValidity(true)
}, [])
// Your InnerBlock, etc...
} |
Hello!
this breaks the blocks showing errors in console bc an undefined variable, so I removed this code and now it is working, just want to let you know if someone face the same problem using this TemplateValidity. |
This seems related: #49005 |
I had a look into this. An issue with trying to augment the current template validation system is that the I think the option mentioned by Riad, where the template for each level passed down during rendering is the only way to solve this, as that's the only place where the template and the inner blocks are fully known. It also makes it possible for inner block templates to override outer block templates, though if it works that way there are two things:
Another thing that stands out to me is that the way invalid templates work differently for inner block template compared to the templates provided by post types. The inner block templates automatically sync while the post type ones don't, so when updating this code some care needs to be taken that we don't accidentally 'sync' post type block templates and trash post content. It probably makes sense for it to be part of |
Describe the bug
When creating a post that uses 'template_lock'=>'all' and contains InnerBlocks with templateLock={false}, everything works as it should (top level of the template is locked, but InnerBlock sections are unlocked). But after adding content to those InnerBlocks using the editor, next time you edit that post, Gutenberg prompts, "The content of your post doesn’t match the template assigned to your post type."
To Reproduce
Steps to reproduce the behavior:
Expected behavior
I think there isn't supposed to be an error, but I'm not sure. I can't find this specific issue mentioned anywhere, so I could easily just be doing something wrong, but I can't figure out what it is. If it is user error, then I'm sorry for the trouble.
Additional context
The text was updated successfully, but these errors were encountered: