The inconsistent 'attribute_array'
, 'attribute'
string, 'classes_array'
, 'classes'
string have been combined together into an Attribute
object. The object can be printed as a string, and accessed and added to like an array. drupal_attributes()
has now been removed in favour of this new class.
Make sure to include the correct Attribute class
use Drupal\Core\Template\Attribute;
To create an Attribute
object:
$variables['item_attribute'] = new Attribute();
By default, Drupal will initialize three Attribute
objects in template_preprocess()
that are accessible in pre/process functions as $variables['attributes']
, $variables['title_attributes']
, $variables['content_attributes']
. For all of these, the 'class'
attribute is pre-initialized to the empty array. If more are needed, initialize a new one via
$attributes = array('class' => array('class-1', 'class-2'));
$variables['item_attribute'] = new Attribute($attributes);
Attributes can be added to the object either when passed in initially (like above) and as needed using array syntax.
For example, to add an ID:
$variables['item_attribute'] = new Attribute();
$variables['item_attribute']['id'] = 'my-id';
There are three types of attributes: array
, string
, and boolean
.
string
is the most common type, and can be seen above in the ID example.
Classes are an example to use array
for. When using array
, you must initialize the array first before adding items.
$variables['item_attribute'] = new Attribute();
$variables['item_attribute']['class'] = array();
$variables['item_attribute']['class'][] = 'class-1';
Use this so different classes can easily be removed/added as needed.
It will print out as a string with each item separated by a space, e.g.:
<div class="class-1 class-2"></div>
Boolean is for HTML boolean attributes that are either on or off (not ones that can contain the value TRUE/FALSE, as those can also contain other values). For example, the disabled attribute. When seen in a tag, it looks like:
<checkbox disabled>
$variables['item_attribute'] = new Attribute();
// This will print just "disabled", not disabled="disabled"
$variables['item_attribute']['disabled'] = TRUE;
// To remove it, so it prints no output.
$variables['item_attribute']['disabled'] = FALSE;
Please use lowercase for key names and always use array syntax for classes.
When upgrading themes, change:
PHPTemplate (7.x):
<div class="<?php print $classes; ?>"<?php print $attributes; ?>>
to Twig (8.x):
<div class="{{ attributes.class }}"{{ attributes|without('class') }}>
However, this:
<div{{ attributes }}>
will print out the same. When printing out individual attributes to customize them within a template, use the Twig "without" filter to prevent attributes that have already been printed from being printed again.
You can also instantiate and print an Attribute
inline. This is functionality equivalent to calling the old drupal_attributes()
with the same arguments.
$output = '<span' . new Attribute(array('class' => array('first', 'last')) . '>some text</span>';
Comments
Note that when you switch
Note that when you switch from drupal_attributes() to new Attribute() you may have to add the following to the top of every file that creates a new Attribute. You'll know that it is needed if you see a message that the Attribute class doesn't exist.
Beware when reading attributes
Beware when reading attributes: by design, this class doesn't output an HTML attribute if it's already been accessed.
See http://api.drupal.org/comment/49228#comment-49228 for more information.
I have explained why this happens
I have replied to that comment you posted with an explanation of why it happens.
Hopefully that helps people better understand how the Attribute object works.
This has been fixed...
Not sure when the underlying fix went in, but the documentation was changed on 14 Aug 2014 to reflect the new functionality. You can call
__toPrint()
on an Attribute instance and get the same result each time. There is no longer a need to use__clone()
.- Mike