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
#type 'item'
only works within a form.- Link module has to implement a second field formatter, because there is no way to render a compound element with a
#title
and#markup
.
Goal
- Eliminate Link module's
'link_separate'
field formatter (merge it into'link_default'
).
Proposed solution
- Make
#type 'item'
work outside of a form context. Make it produce a heading (label is only allowed within a form) and markup, like so:
<div class="item"> <h4>Label, as provided in #title</h4> Content, as provided in #markup (or rendered children). </div>
Related issues
Comment | File | Size | Author |
---|---|---|---|
#39 | theme.item_.39.patch | 5.74 KB | vprocessor |
#19 | theme.item_.19.patch | 8.38 KB | sun |
Comments
Comment #1
sunLike this.
Comment #3
sunUmph. Apparently, a couple of core modules are using #type 'item' in very unusual ways.
Since I don't want to rewrite half of core for this patch, I added the necessary properties and behavior to support those unusual usages. Specifically:
- Some modules do not specify a #title.
- Some specify only #markup and #description.
Comment #5
sunRe-rolled against HEAD.
Comment #7
sunClosely related: #1848874: Clean up and simplify user cancel methods and processing
Comment #8
sunComment #9
sunManual/visual testing:
The classless H4 heading causes problems, since headings usually get a top+bottom margin of 1em. Options:
1) Do not use a heading, but
div.label
(as in #882666: Core form descriptions shouldn't use a label when not associated with a form) — in hindsight, I don't really like that idea, since it abuses an HTML element to look like another. If something should look like a heading/label, then it should be formatted as one.2) Apply a class to the heading, so the margin can be force-removed.
3) Use a higher/smaller heading element (e.g., H6). This probably still requires 2), not only for the margin, but also for the font-size.
I guess that would leave us with
h4.label
and accompanying CSS styles to remove the margins and inherit the font-size.Comment #10
sunComment #12
sun#10: theme.item_.10.patch queued for re-testing.
Comment #13
sunI consider this patch ready. :)
Comment #14
sunMerged HEAD.
Comment #15
sun#14: theme.item_.14.patch queued for re-testing.
Comment #17
sunMerged HEAD.
Comment #18
sunAlrighty. So here's my stance on the current patch:
I'm 100% confident that making #type 'item' work as a render element outside of forms is a good idea.
I had a dozen of use-cases for that in the past already. That change looks complete to me.
I'm only 60% sure of the Link field formatter change, which merges the 'separate' formatter into the 'link_default' formatter.
The idea is that the 'separate' formatter shares most of the formatter settings, prepare and view code with the default link formatter. The actual difference between both is merely that the 'separate' formatter outputs the link title and link URL as separate HTML elements (as the formatter name suggests).
To clarify, this is what 'link_default' outputs:
And this is what 'separate' outputs:
Both formatters share a couple of settings that allow to control whether to output the URL as plain-text (instead of a link) and so on. Also, the code to sanitize the values as well as applying tokens is almost identical.
I don't know what our current guidelines are with regard to "When, exactly, does one implement a standalone formatter instead of formatter settings?"
In other words, is a formatter defined by its technical behavior? Or is it defined by its resulting markup?
Because, if it's the markup that makes up a formatter, then the 'separate' formatter definitely produces different markup and should probably stay its own formatter... But if the markup does not play a key role - or if the marginal difference outlined above is not deemed to be sufficient - then it would be OK to merge them.
Perhaps I should move the Link formatter change into an own issue?
Comment #19
sunCreated a separate issue for the Link formatter change: #1867822: Leverage new #type 'item' for Link field formatter (merge 'link_separate' formatter into 'link_default')
Removed Link formatter changes.
Comment #20
sun#19: theme.item_.19.patch queued for re-testing.
Comment #21
sun#19: theme.item_.19.patch queued for re-testing.
Comment #23
sun#19: theme.item_.19.patch queued for re-testing.
Comment #24
swentel CreditAttribution: swentel commentedMakes a lot of sense. The example in the summary has a wrapper like
<div class="item">
, however, when testing, I don't see that in the markup, unless I'm doing something wrong. Or don't you want to add that wrapper anymore ?Comment #25
sunYep, that's intentional, since a wrapper is not logical in all cases:
Of course, we could decide that all items should always get at least an .item class on a wrapping DIV, but in evaluating this patch across core, I wasn't able to see why that should be necessary (and it resulted in some divitis). There's a counter-argument of reliability, of course. Perhaps we need to always add a wrapper in order to allow JS and CSS to reliably target elements.
Comment #26
swentel CreditAttribution: swentel commentedWould allow to target for #ajax calls as well I guess, so my best guess would be to add it by default, although in the end I can live with none as well :)
Comment #27
sunYeah. But if it's always wrapped in a DIV, then... what's the actual difference to #type 'container'...?
Would it make sense to remove #type 'item' altogether and move the #title » h4.label processing as contained here into #type 'container'?
Comment #28
mgiffordJust adding a link to #1886728: Switch from details to fieldset when collapsing isn't needed where @sun @nod_ & I were discussing forms & containers.
Would be really good to have some UI patterns that are semantically correct to help us group form elements. In many cases I do think that a styled
<div>
is going to be the right choice.Comment #29
sunFor #ajax and #states, we'd actually need a HTML ID in #attributes, which in turn means that we need a #pre_render to call
element_set_attributes()
(e.g., like all form elements).Second, when appearing inside forms, we could automatically translate #name into an HTML class on the wrapping container; e.g., '[#name]-wrapper'. That should be sufficient for theming.
But when appearing outside of forms, and if there are no #attributes, then I think we do not need a wrapping container, since that would be a DIV without any attributes, which doesn't make sense.
I think we should definitely try to get this in for D8. Perhaps first as #type 'item', to make sure it lands? But with the possible clean-up of merging 'item' into 'container'.
What do you think?
Comment #30
jibran#19: theme.item_.19.patch queued for re-testing.
Comment #31.0
(not verified) CreditAttribution: commentedUpdated issue summary.
Comment #32
sunNote that #2002336: Introduce a CSS class to hide borders of fieldset elements introduced a new #type 'fieldgroup' that essentially resolves part of this use-case here, but only within a form context, because it is a
<fieldset>
.The original use-case here was targeting output outside of a form context; e.g., Link field formatters just want a "label" followed by custom #markup/#children.
Comment #34
andypostComment #35
vprocessor CreditAttribution: vprocessor at Skilld commentedComment #36
Manuel Garcia CreditAttribution: Manuel Garcia at Appnovation commentedComment #37
Manuel Garcia CreditAttribution: Manuel Garcia at Appnovation commentedI had a look, but this isn't just a standard reroll... we have to do things differently nowadays. Below my humble review:
Theme function is gone now, and this change is already in Drupal\Core\Render\Element\Number::preRenderNumber()
I don't think we should be adding new theme functions.
theme_link was removed [#2061877]
Same, we should probably add a new #type instead?
Comment #38
vprocessor CreditAttribution: vprocessor at Skilld commentedComment #39
vprocessor CreditAttribution: vprocessor at Skilld commentedrerolled