1

I need to be able to change attributes (like class, data-toggle, data-direction) of the label itself, at a PHP level, in a way that will support conditions in form definition function.

The solution given in How can I add a class to a label? doesn't work for my problem, as they are only workarounds that will not work with the theming JavaScript I need to expose my data to. Also, they are pretty much limited to styling, and that's only one of the attributes that may be needed.

I'm OK with only having limited, predefined sets of attributes, as long as I can select one at the time of form building.

3
  • Results of googling are, sadly, "impossible" and "apply class to div created with #prefix and #suffix, then use it to theme". Does not work for me.
    – Mołot
    Commented Nov 18, 2013 at 13:14
  • If its just for theming purpose, use jQuery to add/remove attribute with attr() or prop()
    – user12947
    Commented Nov 18, 2013 at 13:21
  • @JhilkeDai I hoped I made it clear it is not really possible. That's the way I'm doing it now, when adding error-related properties, but when applied in behavior, on element's first appearance, it conflicts with the other (externally maintained) library. that's why I'm looking for PHP-side solution. Best thing would be something like #atributes themselves, but applied to label, not field.
    – Mołot
    Commented Nov 18, 2013 at 13:27

1 Answer 1

2

Solution is to implement theme_form_element_label.

Changing one line from:

$attributes = array();

to:

$attributes = isset($element['#label_attributes'])?$element['#label_attributes']:array();

in your implementation makes it possible to use '#label_attributes' just the way you would use normal #attributes.

NOTE: If your parent theme defines this function already, then you need to copy function from parent theme, not from form.inc.


Full implementation, to put in template.php:

function mymodule_form_element_label($variables) {
  $element = $variables['element'];
  // This is also used in the installer, pre-database setup.
  $t = get_t();

  // If title and required marker are both empty, output no label.
  if ((!isset($element['#title']) || $element['#title'] === '') && empty($element['#required'])) {
    return '';
  }

  // If the element is required, a required marker is appended to the label.
  $required = !empty($element['#required']) ? theme('form_required_marker', array('element' => $element)) : '';

  $title = filter_xss_admin($element['#title']);

  // NOTE: CHANGED LINE BELOW!
  // If there are attributes already, use them. If not, create empty array.
  $attributes = isset($element['#label_attributes'])?$element['#label_attributes']:array();

  // Style the label as class option to display inline with the element.
  if ($element['#title_display'] == 'after') {
    $attributes['class'] = 'option';
  }
  // Show label only to screen readers to avoid disruption in visual flows.
  elseif ($element['#title_display'] == 'invisible') {
    $attributes['class'] = 'element-invisible';
  }

  if (!empty($element['#id'])) {
    $attributes['for'] = $element['#id'];
  }

  // The leading whitespace helps visually separate fields from inline labels.
  return ' <label' . drupal_attributes($attributes) . '>' . $t('!title !required', array('!title' => $title, '!required' => $required)) . "</label>\n";
}
2
  • Thank you, I used this implementation. I want to add that the inline option overwrote my class attribute so I changed: $attributes['class'] = 'option'; to $attributes['class'][] = 'option'; (same with the other two) so they won't overwrite any attributes I set.
    – andrbmgi
    Commented Nov 18, 2014 at 23:53
  • @andrbmgi Hello, glad it worked. If you have a follow-up question, please ask it as a question :) If it's only a clarification, then OK.
    – Mołot
    Commented Nov 19, 2014 at 6:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.