2

I've got a field collection with has a div wrapper with the classes "field-collection-container clearfix" I'd like to add an additional class to this div. How would I go about this?

I've tried this:

MYTHEME_preprocess_field(&$variables, $hook){
    if($element['#field_name'] == "FIELD_COLLECTION_NAME"){
        $variables["element"]["#prefix"] = '<div class="field-collection-container clearfix MY_CLASS">'
    }
}

But this doesn't seem to have any affect. I'm not sure what else to try, I also found an answer here https://drupal.stackexchange.com/a/142389/39899 but that doesn't seem to do anything either. The code I put above actually runs as I did a var_dump() and saw the results but when I tried that with the answer I linked to I got nothing.

[UPDATE]

Just to clarify, I'm looking specifically to amend the div with the class "field-collection-container" not add another wrapper. The reason being that I think it's just tidier to make use of the markup Drupal already outputs rather than just adding more do it.

4

The wrapper containing the 'field-collection-container' class is added in field_collection_field_formatter_view() and because of this it seems that the usual theme functions (e.g theme_field, templatee_preprocess_field and template_process_field) are not able to alter the #prefix.

I've found that it is possible to alter the #prefix by altering the field collection field at the point it is attached the the parent entity by implementing hook_field_attach_view_alter() in our theme (in template.php):

/**
 * Implements hook_field_attach_view_alter()
 */
function MYTHEME_field_attach_view_alter(&$output, $context) {

  // First check we're dealing with a field collection field.
  if(!empty($output['field_link_collection'])) {

    // Now check for our specific field collection field.
    if ($output['field_link_collection']['#field_name'] === 'field_link_collection' ) {

      // Alter the prefix.
      $output['field_link_collection']['#prefix'] = '<div class="field-collection-container clearfix MYCLASS">';
    }
  }

}

Make sure you replace 'field_link_collection' with the machine name of your field collection field.

Field collections are entities themselves (containing fields) as well being fields attached to other entities which is incredibly powerful but I've found to be confusing when trying to alter specific things.

I think that in this case accessing theme_preprocess_field doesn't change anything as it's the wrong point in the render chain and the field is instead being rendered through field_formatter_view (I'm not certain that this is the case though, it may be more complex).

It might also be useful to look at the Display Suite module as it gives you much more control over the markup Drupal generates.

If you wanted to make this easier in the future, submitting a patch to the field collection module to declare a template in field_collection_theme() would help, this issue looks related.

UPDATE

Another method is to change the field display settings (in 'manage display' of the node) of the field collection field from 'field collection items' to 'fields only'. There should still be a wrapper div which you can amend the classes of by doing something like:

function MYTHEME_preprocess_field(&$variables) {
  if($element['#field_name'] == "FIELD_COLLECTION_NAME"){
    $variables['classes_array'][] = 'MYCLASS';
  }
}
  • I used the first method & it worked great, thank you very much. To anyone reading this the "field_link_collection" needs to be replaced with the machine name of your field collection. Thanks very much for the good explanation too! – Neil Nand Jul 5 '15 at 1:55
  • I had one question on this though, if I'm correct the "field_link_collection" array key & the value of $output['field_link_collection']['#field_name'] will be the same, if so why is there a conditional statement checking the value of both? – Neil Nand Jul 5 '15 at 1:56
  • Yes good point about making sure to replace the field collection machine name, I've update the answer to make this clearer. If we were to only check $output['field_link_collection']['#field_name'] === 'our_field_name' this would produce a PHP notice if this wasn't defined (which I think is the case on non field-collection fields). Also as a general point I think that field_attach_view_alter() is called on lots of fields, so we want to be really careful about making sure everything is set properly and we're only acting on the field we want to act on. – Hedley Smith Jul 5 '15 at 11:47
  • Thanks for clearing that up, makes sense having both conditionals now. It's all working perfectly so thanks again for the help. – Neil Nand Jul 5 '15 at 14:33
  • No problem! It was interesting to look through, I'm putting together a base theme soon which may use some of this solution, it's going to be called 'CEMS'. – Hedley Smith Jul 5 '15 at 17:05
0
  1. Your function missing parameters $variables
  2. theme_field use file template to show html. You can see source . In source don't use variable $element only use $items. So your html don't change anythink.
  3. You can add wrapper with overwrite file tpl with suggestions. So easy with file name field--FIELD_COLLECTION_NAME.tpl.php and overwrite to html you want.Or can overwrite function theme_field() (copy to file template.php and clear cache.)
function YourTheme_field($variables) {
  $output = '';

  // Render the label, if it's not hidden.
  if (!$variables ['label_hidden']) {
    $output .= '<div class="field-label"' . $variables ['title_attributes'] . '>' . $variables ['label'] . ':&nbsp;</div>';
  }

  // Render the items.
  $output .= '<div class="field-items"' . $variables ['content_attributes'] . '>';
  foreach ($variables ['items'] as $delta => $item) {
    $classes = 'field-item ' . ($delta % 2 ? 'odd' : 'even');
    $output .= '<div class="' . $classes . '"' . $variables ['item_attributes'][$delta] . '>' . drupal_render($item) . '</div>';
  }
  $output .= '</div>';

  // Render the top-level DIV.
  $output = '<div class="' . $variables ['classes'] . '"' . $variables ['attributes'] . '>' . $output . '</div>';

  return $output;
}
  • Thanks for the answer, the missing parameter was a typo on my part but the code I'm actually using does have it. I cannot see how to edit the specific wrapper with the class "field-collection-container" with either theme_field or a .tpl file. I realise I can add my own wrapper in but I was looking to alter what is already there, the reason being that Drupal outputs so much markup as it is I'd rather not add more to it and just amend what it already outputs. – Neil Nand Jul 3 '15 at 3:07
  • I've updated my example now to fix the typo. – Neil Nand Jul 3 '15 at 3:10
  • Or you can overwrite function theme_field() you can't edit html is there. Code above, you can edit your self. – MrD Jul 3 '15 at 3:29
  • Thanks for the update to your answer, that was pretty much the code I was using (I took mine from the Drupal documentation) but it just seemed as though it only edited the content within the .field-collection-container div not the div itself. Thanks for the answer though as I've learnt a fair bit from what you wrote. – Neil Nand Jul 5 '15 at 3:05
0

I didn't ever want extraneous prefix and suffix HTML around my fields (I'd rather know exactly what's there by writing a template file), so I modified the answer here to scrub them all -- obviously, some people may want their prefixes and suffixes, but if not, this is a way to wipe them out generally without having to specify field-by-field:

/**
 * Scrub prefixes and suffixes from fields in output.
 *
 * Implements hook_field_attach_view_alter()
 */
function bartik_field_attach_view_alter(&$output) {
  if (is_array($output)) {
    foreach ($output as &$field) {
      if (isset($field['#prefix'])) {
        $field['#prefix'] = '';
      }
      if (isset($field['#suffix'])) {
        $field['#suffix'] = '';
      }
    }
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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