Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
This is what I had to do to get AjaxResponses in a multistep form for entity_embed for media.
$output = drupal_render($rebuild_form);
drupal_process_attached($rebuild_form);
Just calling drupal_render here should have been sufficient, requiring black magic knowledge.
Proposed resolution
- Deprecate drupal_merge_attached and move to a static method call.
- Allow ajax commands to accept render arrays with #attached assets.
- Consolidate the duplicate calls to setAttachments internally when rendered by the command.
User interface changes
None
API changes
drupal_merge_attachments()
deprecated in favour of Renderer::mergeAttachments
Task | Novice task? | Contributor instructions | Complete? |
---|---|---|---|
Reroll the patch if it no longer applies. | Instructions |
Beta phase evaluation
Issue category | Bug because developers expect render arrays can be passed to ajax commands just as they are to other rendering operations and have their #attachements attached |
---|---|
Issue priority | Critical because developers expect this to work in a particular way, triaged in #25 |
Comment | File | Size | Author |
---|---|---|---|
#55 | ajax-assets-attach.55.patch | 20.36 KB | Wim Leers |
#47 | Screen Shot 2015-01-22 at 2.58.10 pm.png | 54.55 KB | kattekrab |
#47 | Screen Shot 2015-01-22 at 2.57.46 pm.png | 56.8 KB | kattekrab |
#47 | Screen Shot 2015-01-22 at 2.57.35 pm.png | 41.7 KB | kattekrab |
#47 | Screen Shot 2015-01-22 at 2.58.42 pm.png | 76.96 KB | kattekrab |
Comments
Comment #1
Wim LeersWorking on this one. I worked with dstol to figure out the root cause, and the root cause is my patch in #2273277: Figure out a solution for the problematic interaction between the render system and the theme system when using #pre_render. Figuring out a solution to clean this all up.
Comment #2
Wim LeersClosed the following as duplicates:
Comment #3
catchComment #4
dawehnerOne basic thing we could be done is to extend the ajax commands to accept render arrays and then handle that there.
Comment #5
Wim LeersI was thinking along the same lines.
Comment #6
Wim LeersAnother issue about this was filed: #2369151: Errors in wysiwyg image modal forms break the go to url after submit.
Comment #7
Anonymous (not verified) CreditAttribution: Anonymous commentedI closed another issue as duplicate: #2368231: "remove" action on image field in "article" causes fatal error from quick edit mode
It is an exact copy of #2 bullet 3.
Comment #8
dawehnerI wonder whether we could introduce something like
drupal_render_with_attachments
?Comment #9
Wim LeersAnother issue about this was filed: #2373703: Image upload via WYSIWYG modal incorrectly redirects.
I'm now actively working on this.
Comment #10
Wim LeersAnd another issue about this was filed, this time for Quick Edit module: #2374921: It is not attaching the javascripts in Quick Edit.
Comment #11
mnico CreditAttribution: mnico commentedHi, in this issue description the author says: "Just calling drupal_render here should have been sufficient" and this is already happening in Drupal 7 but for some reason in Drupal 8 the function "drupal_process_attached" was removed from "drupal_render" even though it is stated in the documentation.
I have tested that these issues were solved by this patch
Comment #13
mnico CreditAttribution: mnico commentedUps my bad, I had not seen this #2273277: Figure out a solution for the problematic interaction between the render system and the theme system when using #pre_render
Sorry :P
Comment #16
dawehnerUnassigned Wim, because that probably demotivated people from rerolling the patch.
Comment #17
Wim LeersWell, actually was planing to solve this as part of #2368797: Optimize ajaxPageState to keep Drupal 8 sites fast on high-latency networks, prevent CSS/JS aggregation from taking down sites and use HTTP GET for AJAX requests, because they touch the same areas. The quick fix is just adding
drupal_process_attached()
everywhere, but that's terrible DX, so we don't want to introduce that.That being said, a patch to do #4:
would be fine, because I could still refactor that later.
Comment #18
yched CreditAttribution: yched commentedhaven't been following closely, but that sounds a bit concise for a novice (it does for me ;-)
Like "which ajax commands should do what where ?"
Comment #19
Wim LeersThis is why I was tempted to remove the "Novice" tag :)
Comment #20
Wim LeersAnd another duplicate: #2387205: Insert Image modal redirected to image upload form. The 8th report!
Comment #21
tadityar CreditAttribution: tadityar commentedre-rolled the patch, review for testbot testing.
Comment #23
aneek CreditAttribution: aneek commented@tadityar, the patch is not correct I think Gives PHP syntax errors in bot. Please verify once. To get some help you can follow Making a Drupal patch with Git & Advanced patch contributor guide links.
Thanks!
Comment #24
star-szrIt sounds like this needs a new patch based on #17 rather than a reroll.
Comment #25
alexpottDiscussed with @xjm, @catch, @effulgentsia. We decided that this is critical because it how developers expect things to work - as shown by the fact that we have 8 reports of this already.
The issue summary needs an update to detail the solution and it would be great if we could have a test.
Comment #26
DickJohnson CreditAttribution: DickJohnson commentedAssigned to myself. Working on this during next 24 hours based on #17 and #25.
Comment #27
DickJohnson CreditAttribution: DickJohnson commentedComment #28
mondrakeNew start then :)
This patch allows AJAX commands that require HTML input, to accept alternatively render arrays. If a render array is passed, then it is rendered to HTML by the Ajax command, and it is passed through
drupal_process_attached()
as well.Calls to Ajax commands in code should be adjusted, either here or as follow-ups. I started converting only the calls in the editor module's
EditorImageDialog
andEditorLinkDialog
classes, and it seems that the issue reported in #2387205: Insert Image modal redirected to image upload form is fixed by this patch.Comment #29
dawehnerAdding the possibility to pass along render arrays totally makes sense IMHO.
I'd love to do that lazy, which means we just render it, when the result is rendered.
Comment #30
mondrake#29 something like this?
I am starting to wonder whether it would make more sense to accept *ONLY* render arrays for input (i.e. typehint the $content variables to array), instead of either HTML or render array. It would simplify the code and make it more consistent (see e.g. the
::drupalAttachLibrary()
method inOpenDialogCommand
, that could be dropped entirely). Also calling code would benefit from having to behave to pass render arrays instead of making drupal_render() calls. OTOH, it would be an API change and require quite some work to convert all the calling code.Opinions?
Comment #31
dawehnerI would argue it is an API change which is not worth to do.
On top of that pure API change level, you could also argue that your APIs should be decoupled, so there is nothing wrong with supporting strings as well.
Comment #32
larowlanCould this be a trait? Seems nearly identical.
The trait could also include a method getRenderer() and setRenderer() which would replace the \Drupal::service('renderer') and allow unit-testing.
Comment #33
mondrake#31 ok maybe not generally, however at least forOpenDialogCommand
andOpenModalDialogCommand
I would suggest to change to render array only - isn't it that you would have to pre-render an array in calling code in any case?Proposing that here.From a quick look at the developments in #2368797: Optimize ajaxPageState to keep Drupal 8 sites fast on high-latency networks, prevent CSS/JS aggregation from taking down sites and use HTTP GET for AJAX requests it seems that quite some pieces of the same code are being touched by this patch too, shall this be postponed on that?#32 in this patch now the two are diverging so I do not see the need for a trait any longer.Edit:
Retracted the proposal
Comment #34
Wim LeersI'd prefer this to be postponed on that other patch, yes, because the solution in here still relies on the statics in
_drupal_add_(css|js)()
, which are (FINALLY!) being removed in that issue.Once that issue is done, this patch will become simpler though :)
Comment #35
kattekrab CreditAttribution: kattekrab commentedBumped up against this one again during D8 tutorial.
Comment #36
mondrake#2368797: Optimize ajaxPageState to keep Drupal 8 sites fast on high-latency networks, prevent CSS/JS aggregation from taking down sites and use HTTP GET for AJAX requests has landed now. I do not like the patch in #33 anymore as it is going into dire straits (how to decide when to render vs renderRoot, implications on bubbling metadata, etc.). So to keep it simple for now I just rerolled patch in #30 introducing a trait as suggested in #32.
By deferring rendering and attaching assets to the Ajax command, here the risk is what is being filed in #2407201: Consider introducing AjaxResponse::addAttachments(), i.e. the last Ajax command in a response will rule.
Just posting for progress and to run testing, will set as postponed again later.
Comment #37
Wim Leers#2368797: Optimize ajaxPageState to keep Drupal 8 sites fast on high-latency networks, prevent CSS/JS aggregation from taking down sites and use HTTP GET for AJAX requests landed, hence this is now unpostponed. It solved all occurrences of this problem in D8 core. Tempted to make it major instead of critical, but since the DX problem still remains, keeping at critical.
#36: wow! Awesome work! The fact that the various AJAX commands are blissfully unaware of the
AjaxResponse
object was also the main obstacle when I looked into this.Your great work in #36 gave me an alternative idea, which allows us to remove the indirect dependency of the AJAX command objects on the
AjaxResponse
object commands are rendered in. The idea: commands could instead implement anCommandWithAttachedAssetsInterface
, allowing theAjaxResponse
, after invokingCommandInterface::render()
, checking ifinstanceof CommandWithAttachedAssetsInterface
, and if so, getting the attached assets (anAttachedAssets
instance). TheAjaxResponse
can then merge together all theAttachedAssets
objects.What do you think?
#2407201: Consider introducing AjaxResponse::addAttachments() now contains a patch; in the current state of *this* patch, only a single line needs to be changed.
Comment #38
mondrakeRe. #37 why not. Here's a first cut - this however has reintroduced #2387205: Insert Image modal redirected to image upload form, do not know why :(
Will need more work.
Comment #39
Wim LeersThis should be
$this->attachedAssets = AttachedAssets::createFromRenderArray($this->content);
And then the bug you mention should disappear.
Comment #41
larowlanfixes #39
Tagging for office hours
Comment #43
larowlanright
Comment #45
larowlanmore cleanup - drupal_merge_attachments can't be used in a unit test, so moved it to a static method on AttachedAssets and deprecated the old function (retained as a wrapper for now)
Comment #46
larowlanComment #47
kattekrab CreditAttribution: kattekrab at PreviousNext commentedW00t. I just did a manual test to pick up the issue reported a few times around image upload. I'm not sure how to check for the bigger issue here, but this clearly nails
Comment #48
joelpittetI reviewed the code and it seems to be all good. With @kattekrab's manual test in #47 I'm going to stick a fork in this.
Comment #49
Wim LeersAwesome progress here! There is one thing I'm afraid I have to disagree with though:
It's the right thing to do, but the wrong place for that method. It should live on
Renderer
. dawehner moved it there in his patch in #2378883: Convert existing drupal_render() KernelTestBase tests to PHPUnit tests, and I agree with that. This reroll moves it there, but since it's a pure move operation, keeping at RTBC.Also fixed 3 nitpicks (one missing newline, and two times "Definition of …" instead of "Contains …").
Comment #50
larowlanyep, took a stab in the dark, +1 to the move
Comment #51
joelpittetMaybe a couple things that could be fixed on commit and/or ignored nitpicks.
The parenthesis feels a bit strange here, I'd be curious if jhodgdon has any input on this? Maybe just use the word 'via' or 'through' to help convey the attachments are on the '#attached' key of the render array.
Extra line break here. Edit: Better context lines.
Should take a colon at the end of this.
Comment #52
Wim LeersFixed all nitpicks in #51.
Comment #53
alexpottI think that is Renderer::mergeAttachments() and we should have a CR to announce the deprecation.
Let's deprecate this for Drupal 9. We're in beta and there is no compelling reason to remove the function. We can still convert all the usages.
Comment #54
alexpott@Wim Leers pointed out in IRC that drupal_merge_attached was adding in D8 therefore I've changed my mind - it is okay to remove before d8 is released.
Comment #55
Wim Leersdrupal_pre_render_links()
DialogTest
's test code so that both the automatic rendering of render arrays and automatic attaching of assets are exercised. Explicitly testing this would be even better, but this should be sufficient. Keeping at RTBC because it's a tiny change that Alex will either find sufficient test coverage or not.Comment #56
alexpottStill needs an issue summary update to fix the TBD sections.
Comment #57
joelpittetUpdated the issue summary with the beta eval and fixed one TBD and removed the other.
Comment #58
mondrakeJust a small leftover in the IS.
Comment #59
kattekrab CreditAttribution: kattekrab commentedRe ran manual test. Still works. Still RTBC in my view.
Comment #61
alexpottCommitted 8ee0358 and pushed to 8.0.x. Thanks!
Thanks for adding the beta evaluation to the issue summary.
Comment #62
kattekrab CreditAttribution: kattekrab commentedHuzzah!! Such collaboration. :)
Thanks everyone.
and also personal milestone... my 10th commit credit.