If you are using an array for your list items, and specify "class" as an attribute, with a string as the value, which is the expected behavior, theme_item_list assigns your passed string to the 'class' attribute, recasting it as a string, rather than adding it to the class array.
Here's some code to produce this error:
$list[] = array('data' => 'Item one',
'class' => 'first-item');
$list[] = array('data' => 'Item two',
'class' => 'second-item');
theme('item_list', array('items' => $list));
This throws the following error:
Fatal error: [] operator not supported for strings in [...]/includes/theme.inc on line 1840
There is an inelegant workaround for this:
$list[] = array('data' => 'Item two',
'class' => array('second-item'));
Attached is a patch that treats class separately, and checks that it's not an array already, so the above workaround would still work.
Comment | File | Size | Author |
---|---|---|---|
#16 | theme-attributes-doc-1135020-16.patch | 4.53 KB | NROTC_Webmaster |
#13 | theme-attributes-doc-1135020-13.patch | 4.91 KB | NROTC_Webmaster |
theme_item_list-class_attributes.patch | 471 bytes | Anonymous (not verified) | |
Comments
Comment #1
Anonymous (not verified) CreditAttribution: Anonymous commentedI'm noting that this is the same in FAPI as well, so this is perhaps by design. If so, I suggest changing this to a documentation issue so that the theme_item_list page can be updated.
Comment #2
bfroehle CreditAttribution: bfroehle commentedSince one can assign multiple classes to a single item, this is by design. As you mention, the Form API also uses the same syntax:
$form['#attributes'] = array('class' => array('search-form'));
Comment #3
Anonymous (not verified) CreditAttribution: Anonymous commentedChanging this issue to documentation per the discussion above. Suggest changing the first list item under the 'items' variable to:
items: An array of items to be displayed in the list. If an item is a string, then it is used as is. If an item is an array, then the "data" element of the array is used as the contents of the list item. If an item is an array with a "children" element, those children are displayed in a nested list. All other elements are treated as attributes of the list item element. The class attribute should be passed as an array of class names, rather than a string.
Comment #4
Anonymous (not verified) CreditAttribution: Anonymous commentedThis is the link:
http://api.drupal.org/api/drupal/includes--theme.inc/function/theme_item...
I just changed the title.
Comment #5
jhodgdonIn d7, all attributes are arrays, not just 'class'. I don't think we should be singling out class in the doc. Rather we should point out the drupal_attributes() function, which is used to format the attributes.
Needs patch in d8 first, then backport to d7.
Comment #6
star-szrSubscribe - documentation needs some love. IMO we should be able to use both
'class' => 'single-class'
as well as'class' => array('single-class')
but that's just me.Comment #7
jhodgdonRE #6 - that change was made in Drupal 7 after much discussion... So this issue is about updating the documentation so that it makes the functions clearer.
Comment #8
star-szrYup, understood that much. Sorry, probably not the right place to vent :)
Comment #9
NROTC_Webmaster CreditAttribution: NROTC_Webmaster commentedBetween the change already noted and #1317628: Clean up API docs for includes directory, files starting with N-Z can this issue be closed?
(corrected the issue number)
Comment #10
jhodgdonThe suggested change in #5 is to point out that attributes are formatted with drupal_attributes(), which hasn't been done, and I don't see it in that other patch either?
Comment #11
NROTC_Webmaster CreditAttribution: NROTC_Webmaster commentedI'm trying to figure out the best way to handle this.
Seven functions have attributes in the $variables array with most of them making a note that they are an array of some form. The obvious exception is theme_item_list(). Should I a) add @see drupal_attributes() to all of the docblocks or b) just reference it within the description for the attributes of theme_item_list which leaves the possibility that someone else will run into a similar problem.
Line 1568: * - attributes: (optional) An associative array of HTML attributes to apply
function theme_datetime($variables) {
Line 1664: * - attributes: (optional) Attributes for the anchor, or for the tag
Line 1669: * - attributes: A keyed array of attributes for the UL containing the
function theme_links($variables) {
Line 1789: * - attributes: Associative array of attributes to be placed in the img tag.
function theme_image($variables) {
Line 1863: * - attributes: An array of HTML attributes to apply to the table tag.
function theme_table($variables) {
Line 2087: * - attributes: The attributes applied to the list element.
function theme_item_list($variables) {
Line 2200: * - #attributes: (optional) An array of HTML attributes to apply to the
function theme_html_tag($variables) {
Line 2277: * - attributes: Associative array of attributes to be placed in the meter
function theme_meter($variables) {
Comment #12
jhodgdonHmmm... Maybe they should all say:
An associative array of HTML attributes [specifics here, such as "for the anchor tag" etc.]. Attributes are formatted using drupal_attributes().
How's that for an idea?
Comment #13
NROTC_Webmaster CreditAttribution: NROTC_Webmaster commentedTake a look at this and let me know what you think.
Comment #14
jhodgdonLooks good! The only thing I would change is that since we are referencing drupal_attributes(), I think we can take out sentences like this:
If element 'class' is included, it must be an array of one or more class names.
And is that really the complete list of theme functions that use attributes?
http://api.drupal.org/api/drupal/core!includes!common.inc/function/calls...
Wow... looks like there are quite a few... maybe we should reconsider whether we really need to add this sentence to all of them. How necessary is it? Is it common knowledge?
Comment #15
jhodgdonComment #16
NROTC_Webmaster CreditAttribution: NROTC_Webmaster commentedjhodgdon,
Slightly updated patch. In regards to the common knowledge I'm really not sure if it is or not. That seems to be the whole reason this issue was opened so I would lean towards saying no.
Comment #17
jhodgdonAgreed it is probably needed.. but if so, the patch probably needs to expand to encompass all or most of the 48 functions that call drupal_attributes.
And maybe we should change the wording to "Attributes are passed to drupal_attributes() for formatting." just to make it one bit clearer? I'm OK with either way, but I think this wording might make it abundantly clear that you need to supply attributes that that function can format properly.
As one more note, the whole thing of class needing to be an array and not a string is incorrect for drupal_attributes() itself. Some of the functions, however, add their own items to class, such as:
$attributes['class'][] = 'whatever'
So actually just saying that it is formatted with drupal_attributes() may not be sufficient... sigh.
Comment #18
NROTC_Webmaster CreditAttribution: NROTC_Webmaster commented:(
I'll take another stab at it, but if we are adding something to all 48 calls should we just add @see?
I think the documentation for it does a good job of explaining how to use it.
My only hesitation with adding the @see is that the actual use might be lost with all of the other variables listed for the functions.
Comment #19
jhodgdonWe need to be consistent. Either we put it in all 48 (or at least those of the 48 where it's appropriate -- maybe not quite all), or we put it in none of them. I would actually vote for none.
Putting in @see is not going to help IMO, because the See Also section will be far away from the place where people aren't realizing they need to make the individual attributes arrays, and also as I noted above, actually drupal_attributes() doesn't care whether class is an array or a single value, it's just the individual functions that care because they're adding more elements to class.
So... with all this in mind, I am really inclined to call this a "won't fix".
Comment #20
jhodgdonI just marked #1418624: theme_table() [and other HTML element theme functions?] should document class attributes being an array as a duplicate of this one.
Comment #21
jenlamptonTagging this one since we'll need to use a consistent way to document all our attributes in Twig templates too :)
Comment #22
joelpittetDoes this need to be done in D8?
There is no longer
drupal_attributes()
, it's now theAttribute
class. Can this be bumped back down to D7?Comment #23
Arlina CreditAttribution: Arlina commentedThis should be a D7 issue now. The docs are not clear about how to add a class to a <li> item, it just says "All other elements (besides "data" and "children") are treated as attributes of the list item element." This misleads to trying to add a class element as a string (which produces the fatal error), specially since any other element specified as as a string is correctly added as an attribute to the <li>.
Comment #24
joelpittetDropping back down to D7. D8 we are using
Attribute
class and doing things likedrupal_attributes()