-
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
Block editor should work in "headless" mode, without Edit UI mounted #59592
Comments
I agree with your assessments here and would for us to make improvements here. Ideally "edit" should be about rendering the edit only and not about enabling actions/selectors to work properly.
This is the only point that I disagree with in this issue, I think block bindings are already represented in the core/block-editor store using the "source" attributes of the blocks, the same way there's a "ref" attribute for instance in a template part but the template part's properties are not part of the "block-editor" store. |
Thanks for opening this discussion 💯
I also agree. Introducing these components was mainly part of a refactoring process. Everything should happen and be addressed independently of the visual representation of the block in the canvas context or wherever it happens. How to sync actions affect app history is slightly secondary but must be handled carefully. What happens when a new value from an external source updates the bound attribute value? |
If it should be happening somewhere inside the core/block-editor store, does it mean that when the value of the external prop changes, the app should update the data store for all block instances with an attribute bound to it? |
Super draft PR that implements the data propagation in the Mode, out of the context of the View. |
When working on lazy loading block
edit
functions in #55585, I am dealing with a situation where a block already exists (is part of the block tree in thecore/block-editor
store), but its<Edit>
UI is not yet mounted, because theedit
component is being lazy loaded. I am trying to come up with a reasonable "universal edit placeholder" that could be displayed while the realedit
is loading, and that could handle keyboard typing in the interim period.While working on this, one of the surprising findings was that the
edit
component doesn't only provide UI for editing, but also defines some basic block behavior. In MVC language, it's not only "view", but also implements part of the "model". Architecturally, that's bad. Some examples:You can't insert an inner block without edit UI mounted: If you dispatch the
insertBlocks
orreplaceBlocks
action in thecore/block-editor
store, and the edit UI is not mounted, these actions will fail, they won't insert any new blocks. Because thecanInsertBlockType
permission check will returnfalse
-- it determines whether the target block supports inner blocks, and it detects that by checking for presence ofgetBlockListSettings
for that block. But block list settings are set by theedit
React UI, namely theInnerBlocks
component, which callsupdateBlockListSettings
on mount.Default templates are not inserted. Many blocks, when inserted from the slash inserter, will not insert just the block itself, but will also create some default inner structure. List has one inner List Item. Quote and Cover has a Paragraph. Social Links have a set of four default social icons. These are inserted only when the
Edit
UI is mounted. Because the insertion is done by an on-mount effect insideuseInnerBlockTemplateSync
called inInnerBlocks
.Inserting blocks with prefix transforms (
*
-> list,>
-> quote, ...) does the same job differently -- creating the inner blocks is directly inside the transform functions. Therefore, prefix transforms work correctly when headless.Splitting and merging list items: List items have custom merge and split behavior, mostly to account for nested sub-lists, but store actions like
mergeBlocks
don't know about it because it's defined inside theedit
UI and passed as props toRichText
. Ideally, all this behavior should be present in themerge
function defined on the block type registration.Then the merging and splitting could be done headlessly, without
edit
UI mounted. After all, thecore/block-editor
store fully owns and manages the selection, i.e., it knows where the text cursor is, and doesn't need anyedit
UI for that. Theedit
UI should only bind the split/merge operations to keys like Enter or Backspace.Block bindings: We are in the middle of developing block attribute bindings, but are we really doing it right? Block bindings should be 100% a "data problem" -- a block attribute is not stored in the block markup as usual, but is sourced from some other data source... That should be happening solely somewhere inside the
core/block-editor
store, shouldn't it? The actualedit
UI shouldn't need to be aware where the data come from. And yet we have React components for data synchronization likeBlockBindingBridge
orBindingConnector
. That looks suspicious.The text was updated successfully, but these errors were encountered: