Problem
If you create a template file to theme your field collection field (field--field-my-collection.tpl.php
), the tpl cascades through all child fields of that collection.
For example, if you have a collection like:
field-my-collection
-- field-text
-- field-image
and make a template file field--field-my-collection.tpl.php
, the fields that are themed will be:
field-my-collection, and
field-text, and
field-image
This is because the field collection name is also the bundle (aka content type) name for collected fields. Drupal's field tpl inheritance from most specific to least is:
- field--field-name--content-type.tpl.php
- field--field-name.tpl.php
- field--content-type.tpl.php
- field--field-type.tpl.php
So field--field-my-collection.tpl.php
applies to
- field--field-name--content-type.tpl.php
- field--field-name.tpl.php --- for field-my-collection, and
- field--content-type.tpl.php --- for its child fields, field-text and field-image
- field--field-type.tpl.php
Expected Behavior would be that you could create a field collection field tpl that will not apply to all children fields.
Workaround
You can create templates for all of the child fields with the pattern field--field-name--content-type.tpl.php
. This will override field--content-type.tpl.php
.
Proposed Solutions
Rename the field collection bundle to something different than the field collection name.
or
Add a field-collection.tpl.php
, so that no one needs to use field--my-field-collection.tpl.php
anymore.
Original issue description
If you create a template file to theme the top-level, in-the-node field collection's field (field--your-field-collection.tpl.php, not the field collection itself, field-collection-item--your-field-collection.tpl.php), the field--your-field-collection.tpl.php code is also applied to all of the fields within your field collection.
For instance if you were to have a field--your-field-collection.tpl.php with the code
foreach ($items as $delta => $item) {
print render($item) . text('foo');
}
every field inside your field collection will also have 'foo' printed after it.
Not sure if this is desired behavior or not.
Comments
Comment #1
RobW CreditAttribution: RobW commented... and by text('foo') i mean t('foo'). Whoops.
Comment #2
inolen CreditAttribution: inolen commentedJust ran into this today as well, is this intended?
Comment #3
RobW CreditAttribution: RobW commentedIf the maintainers don't have a strong bias either way, my opinion is they shouldn't cascade. In general it's bad practice to create templates to restore default behavior, which you have to if your intent is to only override the field collection's theming.
Comment #4
inolen CreditAttribution: inolen commentedRobW, while it's a bad practice, are you saying I should be able to create a template for my sub-fields to restore the default behavior?
For example, I have a field collection field named "foobar" and in there is a field named "image". I have a custom field--field_foobar.tpl.php that is cascading over the theming of the field_image, however, creating a field--field_image.tpl.php doesn't seem to matter (field--field_foobar.tpl.php takes precedence).
Comment #5
fagoThis isn't desired behaviour, thus it sounds like a bug to me. Anyway I'm open to any solution to this, whatever you think is most useful for themers.
>In general it's bad practice to create templates to restore default behavior, which you have to if your intent is to only override the field collection's theming.
That makes sense.
Comment #6
RobW CreditAttribution: RobW commented>In general it's bad practice to create templates to restore default behavior, which you have to if your intent is to only override the field collection's theming.
Turns out this doesn't work anyway; the field--your-field-collection.tpl overrides all collected fields whether there are per-field tpls or not.
Comment #7
RobW CreditAttribution: RobW commentedIn a comment on another post, Joeysantiago pointed out a tpl that provides a workaround for this issue.
In short, you can use field--your-collected-field--your-field-collection.tpl.php. A more complete example with explanation:
Comment #8
valderama CreditAttribution: valderama commentedthanks a lot RobW, that helped :)
Comment #9
wmostrey CreditAttribution: wmostrey commentedWith the information from #7, isn't this actually a feature that needs more and clearer documentation, instead of this being a bug?
Comment #10
RobW CreditAttribution: RobW commentedI don't think so. For example:
Say you have a node like this:
And say you create a field.tpl.php that sets up default html structure for all the fields on your site (A,B,C,D, Collection 1, and everything over the rest of the site). Now you decide you want your field collections to have a slightly different structure, maybe with an image in the corner. Creating a field--collection-1.tpl.php will theme your collection and all child collections, in this example putting an image in the corner of C and D as well. To revert to default behavior, you have to create both field--collected-field-c--field-collection-1.tpl.php and field--collected-field-d--field-collection-1.tpl.php, and use the exact same code as field.tpl.php. If you had ten collected fields, you'd need ten new tpls just to restore default behavior.
This is messy even in this simplified example -- when you add tpls that do more complicated theming with case switches and field type specific code, it becomes a real pain. Hope that helps you understand my point of view.
Sorry, by the way, for my inconsistent example field naming in different posts.
Comment #11
chalee CreditAttribution: chalee commented+subscribing - This issue is a problem which should be sorted out.
Comment #12
sachbearbeiter CreditAttribution: sachbearbeiter commentedsub
Comment #13
gazwal CreditAttribution: gazwal commentedsub too thx
Comment #14
ufku CreditAttribution: ufku commentedThis is because
field--BUNDLE.tpl.php
overridesfield--FIELD-NAME.tpl.php
.For collection field
BUNDLE
=NODE-TYPE
For sub-fields
BUNDLE
=COLLECTION-FIELD-NAME
That's why
field--COLLECTION-FIELD-NAME.tpl.php
overridesfield--FIELD-NAME.tpl.php
by acting as the BUNDLE of sub-fields.A workaround without defining template files for each sub-field is to rename
field--COLLECTION-FIELD-NAME.tpl.php
tofield--COLLECTION-FIELD-NAME--NODE-TYPE.tpl.php
.Comment #15
idflood CreditAttribution: idflood commentedthanks RobW and ufku for the workarounds. That helped but it still feels like a bug to me.
Comment #16
ufku CreditAttribution: ufku commentedIt's a core bug where field--BUNDLE.tpl.php precedes field--FIELD-NAME.tpl.php.
Comment #17
RobW CreditAttribution: RobW commented@ufku, is there an issue for this open in the core issue queue? Took a quick look but couldn't find one -- just want to check you haven't seen one, maybe oddly named or as part of another issue, before I create a new core issue.
Comment #18
ufku CreditAttribution: ufku commentedI didn't see either.
Comment #19
RobW CreditAttribution: RobW commentedPosted a core issue at #1367354: [PP-1] The list of theme hook suggestions for "field" is incorrectly ordered and has namespacing collisions. I didn't mention field collection, although you're welcome to, just core-specific reasons to revise the cascade. Thanks for pointing out the technical reason for this bug.
Comment #20
mghatiya CreditAttribution: mghatiya commentedI am lost. I have seen good number of threads talking about similar things, but can't get my thing to work.
I have a field collection called "field_result_row" which has fields called "field_rank", "field_direction", "field_team_num" and a field which is a field collection in itself called "field_team_members"
I have created "field--field-result-row.tpl.php" . Is this name correct? Right now this is just a copy of original "field-collection-item.tpl.php" found in field_collection module
My "print render($content); " is not printing anything. So I thought I tried adding following items:
But none of these worked. print_r printed nothing. I am getting error for title saying "undefined variable". and when I put var_dump, I am just getting the white screen.
When I just removed all of these and just added "print ("Test");", the "Test" was printed for all the fields of the collection.
Can someone please give me exact steps with file names etc. as per my field names to clarify things? What I just want to theme is that I want all the fields of the field items to appear in one line. By default they are coming in different lines.
I am sorry I might seem to demand too much, but when someone says create a file with name "your-field-collection-item.tpl.php", it becomes very ambiguous to me as to whether to use underscore or hyphen, whether to add that -- or not, etc.
Thanks so much for reading till here and helping :)
Comment #21
RobW CreditAttribution: RobW commentedmghatiya, here's some brief pointers that hopefully will help you out.
In Drupal 7, double dashes are used between every distinct part of a tpl.php name. Single dashes are used just as you have used them, to make field names, content type names, etc., with more than one word. Example: field--field-name--content-type.tpl.php. Check here for examples.
Your field--field-result-row.tpl.php is correct if you are trying to theme the whole field collection, and as noted in this issue, all the field in it identically. If you want all of the collected fields to appear on the same line, you might try leaving the field collection alone and theming each individual field, replacing the surrounding divs with spans or some other appropriate inline markup. Your tpls would be field--field-rank--field-result-row.tpl.php, and so on. An even simpler option, if you consider the current formatting semantic, is to leave all the tpls at their defaults and style the fields with css. Some well placed display:inline; or float:left; would probably work.
For debugging I recommend you download the Devel module if you haven't already. The devel render tab will give you access to all of your node variables, and dpm($content) will give you the content array in a nice click-to-expand list. Good luck!
Comment #22
mghatiya CreditAttribution: mghatiya commentedThanks for the reply Rob. I'll try it the css way. Will install the Devel module too. I have heard of it, but just that I have observed that adding more modules just slows down drupal and I am wary to add another. But somehow every solution in Drupal points to installing another module :)
But I am still not clear why would print $content or print_r $content will not print anything. As soon as I stop using this tpl file and resort to default, all values are printed, so it is not an issue of display of field being set as hidden. Same is case of why the variable $title is being reported as undeclared. These are all the variables mentioned in the default tpl given with the module.
Comment #22.0
RobW CreditAttribution: RobW commentedEmbetterized the summary.
Comment #22.1
RobW CreditAttribution: RobW commentedtiny edit
Comment #23
RobW CreditAttribution: RobW commentedI think we can leave bundle names alone: creating a
field-collection.tpl
should fix this, since there will no longer be a reason to usefield--field-collection-name.tpl
s. Progress in #1157794: Move markup to template files and improve theming in new 2.x branch.Comment #23.0
RobW CreditAttribution: RobW commentedremoving incorrect formatting
Comment #24
RobW CreditAttribution: RobW commentedWhile working on the tpl patch, I was thinking about this and maybe I was wrong in #23. Even with a field-collection.tpl, child field collections will still have the issue unless we rename the bundle.
e.g.:
field-collection--field-my-collection.tpl.php
will apply tofield_my_collection
, not apply tofield_some_field
, and will apply tofield_child_collection
sincefield_my_collection
is it's bundle.So do we want to rename all field collection bundles something different than the field name? Maybe "collection-field-my-collection"? Other suggestions?
If maintainers are for renaming the bundle I will write the patch.
Comment #25
remaye CreditAttribution: remaye commentedI tried the solution proposed on #7 and could'nt make it work :
- first I created "field--collected-n--field-collection-foo.tpl.php" for each fields of my collection field and it worked : all fields are correctly overriden within the field collection
- then I created a "field--field-collection-foo.tpl.php" using the "field-collection-item.tpl.php" found in the field_collection module, and then the field collection became blank, the $content variable is not even present at the template level.
Unlike mghatiya in #20, if I print "Test" in the "field--field-collection-foo.tpl.php" (and disable "field--collected-x--field-collection-foo.tpl.php") it just prints "Test" one time, not in each fields, just as if the template was not cascaded through the fields as suggest this thread.
I'm confused of what is going on, any idea of what I'm doing wrong ?
Thanks for your time.
Comment #26
RobW CreditAttribution: RobW commentedThe field--field-collection-foo.tpl.php should be based on field.tpl, not field-collection-item.tpl. Field.tpl is basically a wrapper template that will contain all field collection items, where field-collection-item is the tpl for each individual field collection instance.
Comment #27
remaye CreditAttribution: remaye commentedThank you Rob for you quick answer and your pertinence, that was it !
Now works as expected and workaround #7 is fine.
Thanks !
Comment #28
RobW CreditAttribution: RobW commentedNo problem, thanks for the thorough bug report.
Comment #29
JohnAlbinThanks for tracking this down, everyone! I've posted a Drupal core patch over at #1367354: [PP-1] The list of theme hook suggestions for "field" is incorrectly ordered and has namespacing collisions
Comment #30
stevetweeddale CreditAttribution: stevetweeddale commentedI am understanding this correctly, that even if #1367354: [PP-1] The list of theme hook suggestions for "field" is incorrectly ordered and has namespacing collisions were to get committed, there would still be confusion when using field collection? Because the bundle is the same as field name? So would there still be cause to namespace the field collection bundle?
Comment #31
RobW CreditAttribution: RobW commented@steve, correct.
Comment #32
JohnAlbinYeah. The only good work-around is to add a preprocess function to check if the field's name is the name of the collection and then set a custom theme hook suggestion.
To fix this problem altogether, should field collection name its bundles "collection-FIELDNAME"?
Comment #33
RobW CreditAttribution: RobW commentedThat's my suggestion (I might have mentioned it somewhere in the comments above).
Comment #33.0
RobW CreditAttribution: RobW commentedrevised solutions and added original summary
Comment #34
bradallenfisher CreditAttribution: bradallenfisher commentedSemester -> Field Collection
-- Semester Label -> Text Field
-- Course Row -> Field Collection
---- Credits -> Text Field
---- Course Details -> Field Collection -> Machine Name = field_course_details
------ Course Name and Link -> Link Field -> Machine Name = field_course_name_and_link
------ Course Notes -> Text Field
------ Course Requirements -> Select Field
I know this is an old thread. However when deeper nesting is involved such as above, how can i get more specific with my tpl files. I would like to use a tpl file for Course Name and Link.
So far the tpl i can get to fire is:
field--field-course-details.tpl.php which affects all the fields below it as pointed out in this thread. However, what i expected to work is field--field-course-name-and-link--field-course-details.tpl.php but it doesn't. ? Any ideas. drush cc all multiple times.
Comment #35
bradallenfisher CreditAttribution: bradallenfisher commentedI was able to come to a solution on this. however, it is icky :)
Basically you create the parent collection tpl file and add the desire markup or logic.
In my case above i created field--field-course-details.tpl.php and it overrode all child fields.
So i created field--field-course-requirements--field-course-details.tpl which is one of the child fields but i used the default field.tpl.php to "undo" my changes from the inheritance.
YUK. but it works for me until there is a better way.
thanks for this thread... I am going to investigate a way to handle this in a function next.
Comment #36
leanderl CreditAttribution: leanderl commentedThanks for posting this info everyone involved. I ran into this, but it took me several hours to realise that it was the module that was behaving in an unexpected way and not a problem with my implementation of tpl:s in Drupal.
I really find this module useful, perhaps there could be a more clear statement about this "cascading" behaviour in the documentation or in the read-me file? And info about how to address it by "overriding the override". Once you know what's going on, it's a lot easier to tackle.
Comment #37
Ronino CreditAttribution: Ronino commentedI solved this for all cases with a preprocess function in my template.php to remove that malicious theme hook suggestion:
Comment #38
RumpledElf CreditAttribution: RumpledElf commentedApparently this is still an issue in 7.28
Having issues getting the name to hit only the field collection on a vocabulary ...
field--field-collection-name--vocabulary-name.tpl.php
It doesn't work just with taxonomy-term.
Comment #39
lcampanis CreditAttribution: lcampanis commentedWith version 7.x-1.0-beta7, still facing some serious issues in how the templates are processed for BUNDLE.
For some peculiar reason field--my-collection--node-type.tpl.php (or bundle) just doesn't work! I reversed, added all templates, just nothing.
Anything with bundle just won't process as a template at all. Note that all suggestions are in the array and you would expect them to process in order.
The way I got around it is by working with view modes instead. (I honestly don't know why one works and not the other)
That will give you field--my-collection--full.tpl.php, full being the name of your view mode under Display settings for that node type.
Comment #40
skribbz14 CreditAttribution: skribbz14 commentedRonino's work in the THEME_preprocess_field() did it for me as well. Thanks a lot!
Comment #41
graper CreditAttribution: graper commentedI know that this is an old issue, but I found something that I know will help a lot of people with this. I had turned on theme debug mode and found the suggestions that are uses for each field and the children of a collection.
I have a content type named "Procedures" (machine_name:procedure)
in procedures I have a field collection named "Tools Required" (field_tools_required).
inside the collection are 2 fields, and image field named "Image" and a text field named "Description".
The first template file I created followed the same convention as some of the other files, field--field-tools-required.tpl.php. This lead me to here because I too had the same issue of the file be used for the collection and each child field.
I saw some of the work that others had done and as I tracked through the theming and files, I thought it appeared that the file wasn't being provided as a "hook", so I started tracking how to work with theme hooks. That got me to a page to turn on Theme debug mode at https://www.drupal.org/node/223440.
With debug mode on I found that the collection and the child theme are being given the same exact file name suggestions for the theme as one of the suggestions. I also saw other suggestions, so I change the collection to use field--field-tools-required--procedure.tpl.php and that stopped cascading to the child fields.
Instead of using the same collection only template file, I can now use the field--image--field-tools-required.tpl.php named files. This means you don't have to preprocess the field and remove a suggestion.
Hope this is understandable and helps others.
Graper.
Comment #42
jwilson3@Graper, unfortunately, your comment left me confused. What is
field--field-parts-included-procedure.tpl.php
coming from? Your content type name is "Procedures", so I'm having trouble following the mappings of this suggestion... and then at the end, you refer tofield--my-field--my-collection.tpl.php
instead of following through with the example you setup.It would be helpful if you could stick to the concrete example you have for your solution, in order to understand it more clearly. Thanks.
Comment #43
graper CreditAttribution: graper commented@jwilson
Thank you for catching my mistakes. I edited my original post to keep the proper convention. I am working on a node type that has multiple collections so I got things a bit mixed up.
the my-field--my-collection was supposed to be a generic naming convention. sorry about that I changed it also since there seemed to be some confusion on it. Hope this helps.
Comment #44
jwilson3Thanks for the fix. Interesting solution.
Comment #45
efpapado CreditAttribution: efpapado at Ramsalt Lab commentedPlease take a look at https://www.drupal.org/node/715160
I implemented hook_preprocess_field(), where I added
$vars['theme_hook_suggestions'][] = 'field__custom_template_name';
and then I implemented hook_theme_registry_alter() as it is described at the link, and I managed to have my custom template for field collection without problems.
I hope it helps.
Comment #46
yugi CreditAttribution: yugi commentedThe solution suggested by @graper is really helpful and does not require any preprocess or changing theme suggestions.
Basically, you can create a template file followed by the content type that contains the field collection, something in the form of
field--[field-collection]--[content-type].tpl.php
.Comment #47
ronigal CreditAttribution: ronigal commentedThanks graper
Comment #48
jimkeller CreditAttribution: jimkeller commentedPossibly a simpler solution, although possibly brittle if you need to use the word 'collection' anywhere else in your template suggestions:
in THEME_preprocess_field:
Comment #49
rajveergangwarI got the solution from https://www.drupal.org/node/1187990#comment-4699320
Explain:
If your field collection name is XYZ and filed under XYZ is ABC then filed tpl should be
field--ABC--XYZ.tpl
If your field collection name is FIELD_XYZ_MODE and filed under XYZ is FIELD_ABC_DEF then filed tpl should be
field--FIELD_ABC_DEF--FIELD_XYZ_MODE.tpl
Comment #50
Tim Banks CreditAttribution: Tim Banks at Investis Digital commentedThe template suggestion Documentation suggests a similar solution to #39 but that a cleaner way to add to the array would be:
$variables['theme_hook_suggestions'][] = 'hook__suggestion';
So a complete example would look like: