Hi,
This is likely a silly question, but I'm currently trying to theme a multigroup to output in list format instead of divs. I was going to override theme_content_multigroup_display_simple in the site's theme, but I realized that I can't control the container for the multigroup elements from there. The best I can do using that theme override is to change each child element to an LI, but I can't output a UL to wrap them. How is the best way to go about this? Many thanks!

Comments

markus_petrux’s picture

Try with one of the "Table" options. In that case, the theme function gets the whole multigroup, where it renders each subgroup on its own table row. Note that theme('table', ...) is invoked here, so you should be able to render an item list, for example.

markus_petrux’s picture

Status: Active » Fixed

Assuming the support request is resolved. Please, re-open if there's still anything else that needs clarification. Thanks

smithn.nc’s picture

Hi Markus! Yes, that's definitely enough for me to go on. Thank you!

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

matt.nz’s picture

Status: Closed (fixed) » Active

Hi there,

I'm just wondering where I can find more about theming multigroups?

I've searched all over the place, and haven't been able to find anything useful on theming them.

In fact, I've had to resort to hiding multigroup fields and manually displaying them in .tpl.php files, which I'm guessing is a terrible way to do it and has annoying limitations.

Any help is much appreciated.

markus_petrux’s picture

Status: Active » Fixed

@matt.nz: The multigroup offers several display formats, but there's no template for them. This is implemented in content_multigroup.node_view.inc, find the theme functions. Just choose the display format that better suit your needs, then if you need to adjust, override the corresponding theme function in your theme.

techypaul’s picture

Hi,

Not sure if this is what I am looking for, normally with multiple single (!) fields I use something like in my templates;

<?php if($node->field_link[0]['view']!=''){?>
      <?php foreach ($node->field_link as $list) {
      if($list['view']!=''){print $list['view'];}
      }?>
<?php }?>

I assumed I could do something like this:

<?php if($node->group_links[0]['view']!=''){?>
      <?php foreach ($node->field_link1 as $list1) {
      if($list['view']!=''){print $list1['view'];}
      }?>
      <?php foreach ($node->field_link2 as $list2) {
      if($list['view']!=''){print $list2['view'];}
      }?>
<?php }?>

How do I achieve the same thing with multigroups or am I missing the point and it doesnt work like a normal field?

Thanks,
Paul.

csc4’s picture

I'm looking at theming too - of the print view? I have the screen version showing nicely, but can't seem to work out how to present the group as a table for print?

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

techypaul’s picture

Status: Closed (fixed) » Active

Hi,

Really hoping someone might be able to answer #7.

Paul.

markus_petrux’s picture

Status: Active » Closed (fixed)

@paulgrimshaw: try using the method described in #6. The multigroup does not provide templates, but theme functions that you can override to suit your needs.

big_smile’s picture

Hi

I am trying to get my head around this but struggling greatly.

If possible could some one post an example code of a finished theme overide (if possible, with custom

wrapper tags around fields).

I think an example would make this much more clearer.

Thanks!

big_smile’s picture

Status: Closed (fixed) » Active

Also, just to to double check do you put the code in a node-type.tpl.php file or in template.php?

big_smile’s picture

Made some headway and I thought I would post some code snippets that might help other users trying to theme Multigroup - they must all be placed in node-type.tpl.php

$field_NAME-OF-FIELD = $node->content['NAME-OF-FIELD']['field']['#children']; 

<?php if ($field_NAME-OF-FIELD): ?> 
<div><?php print $field_NAME-OF-FIELD; ?></div> 
<?php endif; ?>

^ Prints a non-multi group field (in this case with a div around it)

$group_NAME-OF-GROUP = $node->content['NAME-OF-GROUP']['group']['#children']; 

<?php if ($field_NAME-OF-GROUP): ?> 
<div><?php print $field_NAME-OF-GROUP; ?></div> 
<?php endif; ?>

^ Prints a multi group with all the fields that group the contains (in this case with a div around it).

What I would like to know is how do you print a field that is inside the multi-group? I have tried many variants but none seem to work.
Is it even possible to print a field that is inside a group?

matt.nz’s picture

I'm not sure if this will help, but I've noticed that Contemplate gives you a full breakdown of the node structure to help you design templates. I haven't looked through it to see how multigroup items appear, but it might be able to point you in the right direction?

big_smile’s picture

Hi Matt.nz, thanks for your reply!

I actually spent a lot of timing using Contemplate, before posting.

By deafult, contemplate doesn't recognise multigroup groups. It does recognise the fields within the groups, however, and the default code is as follows:

    <?php foreach ((array)$node->field_NAME-OF-FIELD as $item) { ?>
      <?php print $item['view'] ?>
    <?php } ?> 

This however doesn't print anything!

The variables section of contemplate offers over 40 possible variables for both groups and the fields within groups. However, none of these print any content: they just produce text strings like "array" or the field name.

It seems hopeless! This is a shame as multigroup really improves the usability of Drupal. A complete novice can fill in a form and effortlessly create complex layouts that mix text and photos without having to be confused with things like file field insert or the image options of a WYSIWYG editor.

big_smile’s picture

After a couple more hours poking around, I found the following variable in Contemplate:

<?php print $node->content['group_NAME-OF-MULTIGROUP']['group'][0]['#fields']['field_NAME-OF-FIELD-STORED-IN-MULTIGROUP']['field_name'] ?>

This will print out the title of field that is stored in a multigroup.
(e.g. if you have a field with the name "body text", then it will print the words "body text").

This variable shows that it is possible to access the fields that are inside a multigroup from a node.tpl.php.
However, I am not sure what code you need to print that actual content in the field (as opposed to just its name).
I've tried several variations of the above code to print the data, but no success.

Poking around with Theme Developer suggested that "#value" might work, but it didn't produce any results.

Is there a complete list of properties that Drupal has (e.g. such as #fields, #value, #children, #type, #attributes etc)?
I had a look api.drupal.org, but couldn't find anything.

matt.nz’s picture

Have you tried var_export() on fields that print 'array'?

The details of the fields is available in the content structure:
$node->content['group_attributes']['group'][0]['field_FIELDNAME']['field']['items'][1]['#item']['value']
$node->content['group_attributes']['group'][0]['field_FIELDNAME']['field']['items'][1]['#item']['safe']

and also available under:
$node->content['group_attributes']['group'][0]['field_FIELDNAME']['field']['items'][1]['#children']

Unusually, in my quick test page, it appears the deltas of items started at 1.

This is pretty complex stuff, so I ended just working with fields at the higher level:
$node->field_FIELDNAME[0]['value'];
and formatting them however I needed to. With a foreach(), you can just work out the delta and use it to link together the other fields in the multigroup.

Not the most elegant solution, but definitely less time consuming then working with theme overrides by the sounds of it.

big_smile’s picture

Yeah, Matt.nz! Thanks to your help, I'm getting somewhere!!

As you noted, $node->field_FIELDNAME[0]['value']; lets you access a field stored in a multi-group.
The [0] determines the entry. (So [0] would be the first entry in the field, [1] would be the second entry in the same field and so on.)

Obviously, the following code isn't very efficient:

print $node->field_FIELDNAME[0]['value'];
print $node->field_FIELDNAME[1]['value'];
print $node->field_FIELDNAME[2]['value'];
print $node->field_FIELDNAME[3]['value'];

Just imagine if you had 100 entries!

So to make the code more efficient, I thought I would use a 'count' statement to increase the numbered value (e.g. the [0], [1] etc).
The following example has three fields: body_layout that produces a CSS class, body_heading that produces a heading & body_text that produces text.

<?php $i = 0; 
while ($i <=10) {
print '<div class="'.$node->field_body_layout[$i]['value'].'">
<h2>'.$node->field_body_heading[$i]['value'].'</h2>
<p>'.$node->field_body_text[$i]['value'].'</p>
</div>';
$i++; 
}
?>

This code has some problems:
Firstly, you have to set a limit on the value of $i (in this case '10'), which means you can't have an unlimited number of fields.
I guess that also means that PHP is being asked to do a lot of unnecessary processing work.
Secondly, it 's not very readable!

Does anyone have any suggestions?

matt.nz’s picture

To get around the limited number/unlimited issue, you can use foreach(). It'll loop through however many items are in a multigroup.

foreach ($node->field_body_layout as $delta => $field) {

   print '<div class="'.$node->field_body_layout[$delta]['value'].'">
          <h2>'.$node->field_body_heading[$delta]['value'].'</h2>
          <p>'.$node->field_body_text[$delta]['value'].'</p>
          </div>';

}

On the first line of the print, $node->field_body_layout[$delta]['value'] is the same as $field['value'], which might be less confusing! As for making it more readable, you could put the whole thing into a printf().

big_smile’s picture

Status: Active » Closed (fixed)

Thanks for your help!

Here's a tip for anyone else trying to theme a multigroup:
$node->field_NAME-OF-FIELD[$delta]['value']

The ['value'] part only works if your field contains text. If your field contains images or video, you will need a different entry. The best way to find this entry is to install theme developer and look at the "Dev render" tab. This will let you find what code you need to replace ['value'].

bakr’s picture

If you have configured the multi-group to show sub-group fields as "Columns"

Then you need to render the final output as html table as follows:

      <table width="100%" class="views-table">
      <thead>
        <tr>
          <th>Qualification</th>
          <th>Year Taken</th>
          <th>Academic Institute</th>
          <th>Country</th>
        </tr>
        </thead>
        <tbody>
<? php foreach ($node->field_mg_educ_qualification as $delta => $field) { ?>

      <tr>
        <td><? php print $node->field_mg_educ_qualification[$delta]['value']; ?></td>
        <td><? php print $node->field_mg_pro_year[$delta]['value']; ?></td>
        <td><? php print $node->field_mg_educ_institute[$delta]['value']; ?></td>
        <td><? php print $node->field_mg_educ_country[$delta]['value']; ?></td>
      </tr>

		<? php } ?>
         </tbody>
      </table>

Indeed, you would substitute with the field names at hand.

But I have a problem with formatting the date, any clue?

bakr’s picture

The solution to theming dates is as follows:

<?php print content_format('field_mg_educ_year', $node->field_mg_educ_year[$delta], 'long'); ?>

With Regards to all for the helpful hints that keep the dice rolling!

matt.nz’s picture

Hi bakr,

Good tip. You can also use the theme() function to improve compatibility with themes:


$headers= array('Qualification', 'Year Taken', 'Academic Institute', 'Country');

foreach ($node->field_mg_educ_qualification as $delta => $field) {
  $rows[] = array(
    $node->field_mg_educ_qualification[$delta]['value'],
    content_format('field_mg_educ_year', $node->field_mg_educ_year[$delta], 'long'),
    $node->field_mg_educ_institute[$delta]['value'],
    $node->field_mg_educ_country[$delta]['value']
  );
}

print theme('table', $headers, $rows);

bakr’s picture

Wow, very cool.

I am not familiar with drupal api, but seems can't live without it.

Question:
I am using some jquery to theme the table as sortable and class the odd row.

http://tablesorter.com/docs/

My technique is to add a class="sortable" to the table

$(document).ready(function()
{
$("#.sortable").tablesorter();
}
);

How would I do that through the drupal theming function.

Regards

Thanks Matt.

bakr’s picture

I found solution for advanced table theming at:

http://api.drupal.org/api/function/theme_table/5

and more example on:
http://www.group42.ca/theming_101_%E2%80%93_theme_table_function

Regards

deciphered’s picture

Just a quick note, version 1.5b1 of the Custom Formatters module added the ability to easily theme Multigroups with either a PHP formatter or a HTML/Token formatter.

perke’s picture

I've been able to print multigroup fields in my node.tpl file with

<?php print $node->content['group_link']['group']['#children']; ?>

where "link" is the name of the group

miguel.rincon86’s picture

Hi all,

I want to be able to print a multigroup from a node in a block, or another page so using the node.tpl.php is not a solution for me.

From your suggestions I would think of something like:

 $nid = 1;
$n = node_load($nid);
print $n->content['group_name']['group']['#children']; 

But the content array is not present in the object returned by node_load, I checked the Dev render tab and the node has the 'content' array that I need.

Question:
How to get the node object with the 'content' array?
Or better... How to print a multigroup from anywhere (block, or similar) by having the $nid and the name of the group?

miguel.rincon86’s picture

Status: Closed (fixed) » Active

Moving to active...

pydubreucq’s picture

Hi,
Excuse me I'm French and I don't speak english very well...

I'm using @matt.nz method and It's work fine.

I use variable on header like that :

$header_1= $node->content['group_GROUP_NAME']['group']['#fields']['field_FIELD_NAME']['widget']['label'];
$header_2= $node->content['group_GROUP_NAME']['group']['#fields']['field_FIELD_NAME']['widget']['label'];

$headers= (array("$header_1", "$header_2"));

Bye ;)

pydubreucq’s picture

Hi,
I have a problem with the loop foreach.
On my multigroup I have no obligatory field.
And with that it's possible to forget row...
Thanks by advance ;)
++

matt.nz’s picture

Sorry pydubreucq, can you please explain your problem a little more?

pydubreucq’s picture

Hi,
Sorry for the response time...
And thanks so much for your response.
I've juste found the solution ;)
You can see an example :

Language Add Level
English   Good
  Spanish Excellent

You can see here what I would like to have :

Language Level
English Good
Spanish Excellent

This is my code for do that :

< ?php if(!empty($node-&gt;content['group_GROUP_NAME']['group']['#children'])) { ?>

<fieldset class="content-multigroup-group-GROUP-NAME content-multigroup-display-table-multiple-columns">
<legend><?php print $node-&gt;content['group_GROUP_NAME']['group']['#title']; ?></legend>

// Permet d'afficher la description
<?php print (isset($node->content['group_GROUP_NAME']['group']['#description']) && $node->content['group_GROUP_NAME']['group']['#description'] ? '

<div class="description">'. $node->content['group_GROUP_NAME']['group']['#description'] .'</div>


' : '');
?>

<?php
$rows = null;
// Permet de renseigner les headers du tableau 
$header_1= $node-&gt;content['group_GROUP_NAME']['group']['#fields']['field_FIELD_NAME_1']['widget']['label'];
$header_2= $node-&gt;content['group_GROUP_NAME']['group']['#fields']['field_FIELD_NAME_2']['widget']['label'];
$headers= (array("$header_1", "$header_2"));

//Compte qu'elle est la colonne la plus longue et fournit la liste de tous les elements
if (count($node->field_FIELD_NAME_1) > count($node->field_FIELD_NAME_2)) {
        $long  = $node->field_FIELD_NAME_1;
        $short = $node->field_FIELD_NAME_2;
} else {
        $long  = $node->field_FIELD_NAME_2;
        $short = $node->field_FIELD_NAME_1;
}

//Parcourt la liste prealable et remplis la variable row
$fields = array();
foreach($long as $key => $value) {
        if ($value['value'] == null) {
                $id = $short[$key]['value'];
        } else {
                $id = $long[$key]['value'];
        }

        $rows[] = array(
                $node->taxonomy[$id]->name,
                $node->field_FIELD_NAME_3[$key]['value']
        );

}
print theme('table', $headers, $rows);
?></fieldset>


<?php } ?>

This is my solution, I think it's not the better ;)
Bye

pydubreucq’s picture

Hi all,
I have another question...
I'm using multigroup with "Add Another" but I can't display all group's item...
I just display the first item...
I can see that the values in the first group with the right number of entity
I've try that :

<?php foreach ((array)$node->content['group_experience_resume']['group'][0]['#fields'] as $item ) { ?>
<fieldset class="content-multigroup-wrapper content-multigroup-0">
                <div class="field field-type-text field-field-exp-poste-resume">
                        <div class="field-label"><?php print $node->content['group_experience_resume']['group'][0]['field_exp_poste_resume']['field']['#title'] ?>&nbsp;:&nbsp;
                        </div>
                        <div class="field-items">
                                <div class="field-item odd"><?php print $node->content['group_experience_resume']['group'][0]['field_exp_poste_resume']['field']['#children'] ?>
                                </div>
                        </div>
                </div>
                <div class="field field-type-datetime field-field-exp-periode-resume">
                        <div class="field-label"><?php print $node->content['group_experience_resume']['group'][0]['field_exp_periode_resume']['field']['#title'] ?>&nbsp;:&nbsp;
                        </div>
                        <div class="field-items">
                                <div class="field-item odd">
                                        <span class="date-display-single"><?php print $node->content['group_experience_resume']['group'][0]['field_exp_periode_resume']['field']['#children'] ?>
                                        </span>
                                </div>
                        </div>
                </div>
</fieldset>
<?php } ?>

Thanks by advance ;)

Bye

pydubreucq’s picture

Hi all too,
I've just found the solution ;)
I do like that :

<?php for ($i = 0; $i < count($node->content['group_experience_resume']['group'][0]['#fields']); $i ++) { ?>
        <fieldset class="content-multigroup-wrapper content-multigroup-0">
                <div class="field field-type-text field-field-exp-poste-resume">
                        <div class="field-label"><?php print $node->content['group_experience_resume']['group'][$i]['field_exp_poste_resume']['field']['#title'] ?>&nbsp;:&nbsp;
                        </div>
                        <div class="field-items">
                                <div class="field-item odd"><?php print $node->content['group_experience_resume']['group'][$i]['field_exp_poste_resume']['field']['#children'] ?>
                                </div>
                        </div>
                </div>
                <div class="field field-type-datetime field-field-exp-periode-resume">
                        <div class="field-label"><?php print $node->content['group_experience_resume']['group'][$i]['field_exp_periode_resume']['field']['#title'] ?>&nbsp;:&nbsp;                       
                        </div>
                        <div class="field-items">
                                <div class="field-item odd">
                                        <span class="date-display-single"><?php print $node->content['group_experience_resume']['group'][$i]['field_exp_periode_resume']['field']['#children'] ?>                        
                                        </span>
                                </div>
                        </div>
                </div>
        </fieldset>
<?php } ?>

I put the solution here, if it can help someone like me... :)
Thanks :)

pydubreucq’s picture

Hi,
My last solution was false...
My hook works fine with that :
for ($i = 0; $i < sizeof($node->field_exp_poste_resume); $i ++) {
Bye

mjstone323’s picture

Thanks very much for this and your previous post - it allows for much finer-grained control over the theming of the output.

karens’s picture

Title: Theming a multigroup » Theming a multigroup, create documentation
Category: support » task

The original support request was answered, several times, and closed several times. This thread has been turned into a rambling question about ways to theme the group.

The support issue is closed. Someone can and should try to pull information out of this into the multigroup documentation.

karens’s picture

Category: task » support
Status: Active » Fixed

There is another issue about multigroup documentation, #1086740: Create documentation for content multigroup, I added a link to this issue in that so I can close this issue.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

_siva_’s picture

Hi,
thanks,
I read your post.
Can u tell me how to Change the name of the group . i.e., <legend>Group_name</legend>