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

Redactor fields cannot be initialized when lazy loading new blocks inside Solspace Calendar #790

Closed
superextinct opened this issue Sep 27, 2023 · 7 comments

Comments

@superextinct
Copy link

Bug Description

I have a Neo field containing a Redactor field. After updating to 3.9.2 which includes the new lazy loading behavior, the Redactor field shows up fine when editing an entry.

The same field is also being used inside a Solspace Calendar Event entry. With lazy loading enabled, the Redactor JS field is missing crucial JS (and CSS) assets:

VM489:5 Uncaught ReferenceError: $R is not defined
    at <anonymous>:5:10
    at m (jquery.js?v=1695810053:2:867)
    at Pe (jquery.js?v=1695810053:2:48869)
    at w.fn.init.append (jquery.js?v=1695810053:2:50073)
    at s.constructor.initUi (Block.js:342:18)
    at s.constructor.addBlock (Input.js:314:11)
    at e (Input.js:1110:12)
    at Input.js:1149:9

The affected site is using solspace/craft-calendar:4.0.9

Please let me know if this bug report is better directed at Solspace.

Steps to reproduce

  1. Set enableLazyLoadingNewBlocks to true
  2. Create a new Neo field containing a Redactor block
  3. Add that block to a Solspace Calendar's field layout
  4. Create a new event inside that calendar
  5. Find the Redactor field is missing
  6. Set enableLazyLoadingNewBlocks to false – Redactor field gets initialized correctly

Expected behaviour

No response

Neo version

3.9.2

Craft CMS version

4.5.6

What is the affected Neo field's propagation method?

all

Does this issue involve templating, and if so, is eager-loading used?

This is not a templating issue

@brandonkelly
Copy link
Contributor

I just looked a similar issue (craftcms/cms#13752), thinking it may be related to a change in Craft.appendBodyHtml() in Craft 4.5.6. But also able to reproduce in Craft 4.5.5.

Steps to reproduce:

  1. Create a Neo field that contains a field type that will need to register its own JS files (CKEditor, Redactor, Matrix, etc.).
  2. Place that Neo field in an entry type’s field layout that doesn’t already include any other fields of that same type, so their JS files won’t be preregistered on the page.
  3. Create a new entry of that type, and add a new Neo block.

The issue is that Neo is not capturing any of the JS resources that are registered while rendering a newly-created block. (benf\neo\services\Blocks::renderTabs() is capturing JS code correctly via a buffer, but that won’t include external JS files.)

You can fix by adding the following to the return array in benf\neo\controllers\Input::actionRenderBlocks():

'bodyHtml' => $this->getView()->getBodyHtml(),

Then in your JS code, pass data.bodyHtml to Craft.appendBodyHtml() before appending any of the individual blocks’ JS.

(Note that Craft 4.5.6 did actually introduce a bug that could impact this. Fixed now in 4.5.6.1, so make sure you’re running that.)

@brandonkelly
Copy link
Contributor

Oh, and it looks like this was introduced in Neo 3.9.0.

@ttempleton
Copy link
Contributor

Thanks @brandonkelly. I had originally tried to fix this earlier today by adding the Craft view's startJsFileBuffer() / clearJsFileBuffer() methods to Neo but that didn't pick up anything (related: verbb/hyper#90 (comment)). Are you able to shed some light on why that wasn't working to pick up the registered JS files and why getBodyHtml() would need to be used instead, is there something I'm misunderstanding about how startJsFileBuffer() / clearJsFileBuffer() work?

@lukasNo1
Copy link

I can confirm the issue was introduced in 3.9.0, if i downgrade to 3.8.6 the redactor fields work again (craft 4.5.5)

@ttempleton
Copy link
Contributor

Well anyway, for whatever reason startJsFileBuffer() / clearJsFileBuffer() didn't work for me (likely to be some misunderstanding on my part), getBodyHtml() in combination with getHeadHtml() for the CSS does fix the issue, so this is now fixed in 3.9.4.

@brandonkelly
Copy link
Contributor

@ttempleton startJsFileBuffer() will only capture files that were registered directly via registerJsFile(), but not files that are registered via asset bundles (which don’t get published/included until the end of the request, since the full dependency tree won’t be known until then).

Now that you have getBodyHtml() getting passed down, you could actually drop the JS buffer stuff entirely, since all JS that is registered is expected to be executed together, when it’s appended to <body>. Any JS code will just end up included in getBodyHtml() after the external resource tags.

JS buffering only really makes sense for the way Matrix blocks are added (and presumably Neo before 3.9.0?), where we loop through each of the block types and capture what a brand new block’s HTML and JS should look like up front, but without actually executing the JS until a block is added.

@ttempleton
Copy link
Contributor

Ah okay, that makes sense, thanks 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants