Skip to content
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

Can't edit or preview block widgets in the customizer #25818

Closed
draganescu opened this issue Oct 5, 2020 · 11 comments
Closed

Can't edit or preview block widgets in the customizer #25818

draganescu opened this issue Oct 5, 2020 · 11 comments
Labels
[Feature] Widgets Screen The block-based screen that replaced widgets.php. [Type] Bug An existing feature does not function as intended

Comments

@draganescu
Copy link
Contributor

The new Widgets editor should have it's features present in the customizer as well and preview and update (publish) of changes should work as they currently do.

It appears that there is a problem with making the Customiser auto refresh and auto update the changes made to blocks. (#25157, #25153, #25154)

When the embedded Gutenberg editor in the customiser's sidebar has some changes, the changes are not picked up by the auto preview system, because it expects a certain HTML to exist. Also, it seems the object based architecture of the whole Customiser encapsulates things in a way that makes the widget auto preview API not available if each control is not registered before.

The JS API of the customiser leads to a solution where we don't replace the widgets panel with a full blown editor, but instead we maintain it and each widget will show up as it does today, plus the blocks as a Block widget.

The more complex option is to instance a small editor for each block widget and maybe that would be picked up by the auto preview system, as it contains generic inputs, but no guarantees.

@draganescu draganescu added [Type] Bug An existing feature does not function as intended [Feature] Widgets Screen The block-based screen that replaced widgets.php. labels Oct 5, 2020
@talldan
Copy link
Contributor

talldan commented Oct 6, 2020

Would appreciate some more technical information on this, where should anyone interested in contributing to problem solving this issue look to try to understand the issue? (cc @adamziel, @draganescu )

When the embedded Gutenberg editor in the customiser's sidebar has some changes, the changes are not picked up by the auto preview system, because it expects a certain HTML to exist.

Also, it seems the object based architecture of the whole Customiser encapsulates things in a way that makes the widget auto preview API not available if each control is not registered before.

Some more info on these points would be great, how is it working right now?

@adamziel
Copy link
Contributor

adamziel commented Oct 6, 2020

@talldan the way customizer makes the widgets preview work is this:

WP_Customize_Widgets registers the Widgets panel in the customizer and plugs into a cubic ton of hooks and actions. Whenever a change is made in the customizer UI, the following happens:

  1. A number of hidden inputs gets updated to reflected the change. This happens via jQuery+backbone based javascript targeting specific html structure.
  2. This triggers an XHR that notifies backend about the change. WP_Customize_Widgets updates a preview-related WP option and returns a new changeset ID.,
  3. That changeset ID is then used to request a re-rendered widget from the backend.
  4. Finally, that re-rendered widget is embedded into the preview iframe using JS (without actually reloading the preview).

There is also a lot of both JS and PHP logic in place to make sure the preview will render the updated widget even if you click a link or submit a form. Some of it fakes the value of stored widget options to make sure they're rendered correctly after the page reloads. See WP_Customize_Widgets , preview.js, widgets.js, selective-refresh.js, and another widgets.js.

There are also pencil icons rendered next to every widget in the preview. When clicked, they move the focus to a related form.

Now, the problems are:

  • The frontend JS is tightly coupled with specific HTML structure, input names, elements IDs, and so on.
  • Widgets-specific logic is tightly coupled with the larger customizer JS library.
  • Reimplementing that logic in a more generic way means rewriting thousands of lines of code.

I was able to come up with the following ideas:

  • Keep using the legacy editor, but render mini-Gutenberg as a form for block-based widgets.
  • Still render the legacy Widgets panel, hide it, and create an adapter between the block-based editor and the legacy editor. The adapter would watch changes made in Gutenberg and pass them to the legacy panel pretending to be the user. It would also intercept anything that happens in the hidden panel and reflect it in the Gutenberg. It could work, but it also sounds like it would be pretty fragile, e.g. any stopImmediatePropagetion() or return false in the legacy code could prevent us from listening to events.
  • Make adjustments to legacy code so that it's reusable. It's lengthy and entangled so this could turn into a long and tedious refactor. An alternative would be to duplicate the legacy code and be free from worrying about breaking the existing panel - this could potentially make things easier.

@talldan
Copy link
Contributor

talldan commented Oct 9, 2020

Thanks @adamziel, this helps a lot.

@talldan
Copy link
Contributor

talldan commented Oct 9, 2020

@westonruter Hope you don't mind the ping. Looking back through the code history I notice you've contributed considerably to this part of the codebase. Any suggestions or ideas on integrating the block-based widgets screen?

@westonruter
Copy link
Member

I'm not entirely clear what the scope is here. Is it about adding widgets as blocks, or about “widget blocks” (e.g. Latest Posts) in new block areas? Is this about editing in the Customizer or editing widgets in the admin screen?


When widgets were added to the Customizer originally, there was a ton of work needed to shim the legacy PHP-centric widget UI into the Customizer which is JS-centric. This is why there's all the mess of hidden inputs that are passed around. However, since blocks are JS-based then this mess should be avoidable. A block's attributes can be stored neatly in a Customizer setting, and changes to the Customizer setting will sync automatically to the preview for rendering.

This being said, I think the blocks should really be edited inline in the preview, and the block settings sidebar should be put in the Customizer sidebar. When a block is selected, it could go into edit mode in the preview and then once deselected it can be re-rendered server-side using selective refresh. A challenge here is the editing of the block would be happening in two different windows, and so the settings would need to be synchronized across the windows via postMessage.

@celloexpressions
Copy link

My understanding is that the goal is to allow blocks to be added to widget areas alongside legacy widgets. By doing this widget areas become "block areas".

I agree with everything that @westonruter said. Integrating JS-based Gutenberg blocks with the JS customizer API should not be as difficult as the original widget integration with the customizer was. It seems like the problems with integrating Gutenberg and the customizer to date are that customizer settings are not being leveraged to their full extent.

I also agree that blocks should be edited in the preview (front end). But, based on the non-contextual approach that Gutenberg takes it does seem appropriate to keep widget/block editing separate from the preview in this first step, and then to move all editing to the preview (frontend) eventually. And this would also enable a similar approach to be used for both the wp-admin widgets screen and the customizer. See #26012 for my detailed proposal for using the customize API for both widget screens. If that proposal isn't adopted for the standalone screen, it still applies as an option for widget-blocks in the customizer.

@adamziel
Copy link
Contributor

adamziel commented Oct 15, 2020

This issue initially was about having a new customizer tab that would be a large block editor that would be a customizer-embedded version of the experimental editor. Since that turned out to be pretty challenging, I propose an alternate approach where we embed multiple block editors in the customizer:

#26155

That PR is by no means mergeable, it's more like a discussion prompt cc @draganescu @talldan @celloexpressions @westonruter @noisysocks @tellthemachines

@noisysocks
Copy link
Member

noisysocks commented Oct 22, 2020

Copying some thoughts I had over in Slack here:

Not sure how we reconcile these three points:

  • Can’t put block editor in the right hand preview area because it’s the theme that controls that markup. That’s why FSE changes theming to use blocks
  • Showing both block editor on the left and preview on the right is awkward as it’s two very different WYSIWYG interfaces
  • Need to do something as the goal is to meet users where they are and let them add blocks to where they’re already managing content

Maybe we could make the Customizer a little more modal. Have the left hand side slide out to reveal a full block editor. Then clicking Preview slides it back where it was

Relatedly, I think we should think about adding a Preview button to the non-Customizer widgets editor. If we do that then that would make that screen behave pretty similarly to what I just described above. Maybe these two screens could be unified

@celloexpressions
Copy link

  • Can’t put block editor in the right hand preview area because it’s the theme that controls that markup. That’s why FSE changes theming to use blocks

I wouldn't necessarily say that this is true even without blocks. Why can't the editor work with the markup that the theme provides? And transform it as required while in edit mode. The front end editor plugin has good previous explorations of this concept (pre-block editor): https://wordpress.org/plugins/wp-front-end-editor/

  • Showing both block editor on the left and preview on the right is awkward as it’s two very different WYSIWYG interfaces

For post content, and maybe also widget content, inline editing is probably a better experience, where the sidebar contains block settings similar to the post editor.

Maybe we could make the Customizer a little more modal. Have the left hand side slide out to reveal a full block editor. Then clicking Preview slides it back where it was

I propose this approach as the first step in #26012. There is precedent for this in the customizer's themes panel.

Relatedly, I think we should think about adding a Preview button to the non-Customizer widgets editor. If we do that then that would make that screen behave pretty similarly to what I just described above. Maybe these two screens could be unified

Also proposed in #26012 and seems like a good direction. I agree that #26155 doesn't feel like the right direction.

@noisysocks
Copy link
Member

Why can't the editor work with the markup that the theme provides?

Rendering the block editor requires rendering each block's edit() function. In most cases, markup from edit() won't display properly if inserted into a site's frontend.

There has been some exploration into making it so that the editor uses the actual block markup that is shown on the frontend, which could make inline editing possible. But, to my knowledge, it's still very early days.

@noisysocks
Copy link
Member

I'm going to close this out as we're now tracking the work of adding block-editor to the Customizer in various other places:

Thanks everyone! (Especially @celloexpressions and @westonruter – your notes here were very helpful!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Widgets Screen The block-based screen that replaced widgets.php. [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

No branches or pull requests

6 participants