How to theme a CCK input form.
The reason I have come up with this step by step overview of themeing input forms was that I was working with CCK created content types myself and was trying to figure out how to change the order of the fields of the input form. What I found in the forums was very technical (pointers to the API in 'developer speak') or incomplete, or simply did not cover input forms. There was a lot of help for people looking to modify/theme output, but nothing clear and concise for theming input forms.

So, as a non-developer, semi-technical, marketing/business type person, I set out to discover how to 'theme' my input forms. (all those developers and others that are better informed than I, please feel free to correct me where I am wrong!) I found there are at least two different ways to theme input forms: 1)using the Form API (creating new .module files programmed in php and using things like 'hook_form_alter'), and 2)by creating tpl.php files. I have found that it is far easier to use the second method. You actually end up having to do a little more than create a custom tpl.php file - you have to modify template.php, which requires a little bit of PHP knowledge as well as work with style sheets (either edit style.css or create a new one and link it to your theme - more on this later)

First off, there are a couple people who are responsible for the bulk of the content in the tutorial and deserve proper credit: Lyal (Harostreetmedia.com) thanks for emailing code snippets in the middle of the night, Dublin Drupaller (modernmediamuse.com) thanks for the rich depth of knowledge you share with others on the forums from which I have gleaned and repurposed much, jghyde, who has helped out others on this very same quest and finally Nick Lewis (nicklewis.org) whose website is full of helpful and insightful Drupal information.

Now on with the show.

Assumptions:
1) you understand a little CSS (how it works, how you use class= and id= in HTML tags to style the output)
2) you understand a little PHP (nothing serious, at least the ability to understand what a PHP code snippet is doing so you can copy it and modify it a little)
3) you have CCK installed and know how to create content types with it(although I am referring to CCK input forms in this tutorial, I am pretty sure these are the same steps you would use for any custom node type)

How do you theme a CCK input form?

Step one: create your cck content type
Step two: create a [yourcontenttype].tpl.php file
Step three: modify template.php
Step four: modify style.css

You should be able to modify the input form, pretty much anyway you want with this method. For this example, I am going to do the following: Not show some of the automatically generated 'location' fields (I have 'location' module installed and enabled for my CCK content type, Create my own 'collapsible' group and put the elements that I want to in that group and put some of the input fields side by side instead of each one being on a new line.

Even with the method I am using, there are different ways to accomplish the same thing; for example, I am using tpl.php to order the fields and .css to style them. I think I could just as easily use .css to do everything (but I am no CSS guru) and only use the custom tpl.php file to assign new <div>'s

1.Create a cck content type called 'event_listing' and add some fields to it. I have added contact information, location, event information fields etc.

2.Create at least one node (create an event listing with your new content type)

[insert screenshot here [scr001]

3.Now create a text file called 'event_listing_edit.tpl.php' and put it in the directory of your selected theme (which is somewhere under the '/theme/' directory. For example, my template.php file is found here: /theme/internet_jobs/). You could call this pretty much anything, but it will make a lot more sense and be easier to manage if you call it something like this.

4.now add the following PHP code snippet to the tpl.php file - this is simply sample text to prove that your 'next step' (modifying template.php) is actually working.

<?php print("yahoo, it works!"); ?>

5.Now the hard part - we need to open and edit your template.php file which is again in the directory of your selected theme (in my case it is located here: /theme/internet_jobs/template.php)

6. you will need to add two seperate functions in this file, one to call your custom event_listing_edit.tpl.php file when the form is being edited and another one to call it when a NEW node is to be created (you only need one tpl.php file, but as the template.php file modifications are overriding default functionality, it is necessary to instruct drupal to use the custom file for each case.

At the end of the template.php file, add the following snippets which you should be able to see is two seperate override functions:

// Add Form Start...........jghyde..
if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_event_listing')){
	 function phptemplate_node_form($form) {
	 return _phptemplate_callback('event_listing_edit', array('user' => $user, 'form' => $form));
	 }
}
// Add Form End.................
// Edit Form Start...........Dublin Drupaller..
if ((arg(0) == 'node') && (arg(2) == 'edit')){
    $node = node_load(array('nid' => arg(1)));
		function phptemplate_node_form($form) {
          	return _phptemplate_callback('event_listing_edit', array('user' => $user, 'form' => $form));
		}
}
// Edit Form End........

you can see from the snippets who actually wrote them (although I have modified them slightly from their original) - thank you jghyde and Dublin Drupaller http://drupal.org/node/85908.

7. now try to edit your event_listing node you should see the text 'yahoo, it works' on the page - see screenshot. If you don't get the 'yahoo' message, there a couple of 'suspects' to look at: go check out your naming convention in the template.php file, I tripped up and referred to my tpl.php file incorrectly a few times before I got it right.

[screenshot of 'yahoo it works' scr002.gif]

8. The next step is to add all the fields you want back onto the input form. You can find out what fields are available to your form by putting the following line of code in your custom tpl.php file:
<?php print "<code>"; print_r(array_values($form));print "";?>

You will see a great big long list of information describing the fields available to your input form, the part you are interested in looks like this (there will be a section like this for every field and object on the form):

             [field_website] => Array
                (
                    [0] => Array
                        (
                            [value] => Array
                                (
                                    [link] => www.janze.com
                                    [title] => Janze.com
                                    [attributes] => 
                                )

                        )

                )

In this example, if I want to refer to the website URL, I would refer to it like this:
['field_website']['0']['value']['link'] So if I want to add the website URL to my input form I would add the following line to my tpl.php file:

<div id="jpj8"><?php print form_render($form['field_website']['0']['value']['link']); ?></div>

(I have wrapped the line in a

tag so I can style it using CSS)

Now if I edit my event_listing node, I will get something that looks like this:

[screenshot of form with yahoo and one line with 'field_website' scr003.gif]

don't forget to delete the test line that adds 'yahoo, it works!'

9. Now go ahead and add the rest of the fields you want to the form.

10. If you want to make a group of fields that collapse, all you have to do is wrap those particular fields with <fieldset class=" collapsible"></fieldset> and if you want the Group to have a name add <legend>Contact Info</legend> right after the opening fieldset. Here is an example:

<div class="jpj8aa"><fieldset class=" collapsible"><legend>Contact Info</legend>
<div id="jpj8"><?php print form_render($form['field_name']); ?></div>
<div id="jpj8a"><?php print form_render($form['field_email']); ?></div>
<div id="jpj8b"><?php print form_render($form['field_phone_0']); ?></div>
<div id="jpj8c"><?php print form_render($form['field_website']['0']['value']['link']); ?></div>
<div id="jpj8e"><?php print form_render($form['field_description']); ?></div>
</fieldset></div>

This will look like:

[enter screenshot of contact info section here scr004.gif]

11. Interesting bits
It is a bit odd, but at the end of your tpl.php file you put the

<?php print form_render($form); ?> 

line which will render all remaining form objects (fields and buttons) that have not previously been referred to. That means it will now display all fields that you have not explicitly added in previous lines of code. Now, if you are like me, the reason you didn't explicity add them to the form is because you DON"T want them to be there!

So, to get rid of the fields that have now been automatically added back in, I have found two methods, one that worked for me (that I am sure is 'wrong' because it isn't very elegant) and another that is very elegant, but didnt' work for me. I would definitely try the 'elegant' route first......which is, you have to override unwanted fields explicity in your template.php file. For example, if I do not want to display the website, I put this text $form['field_website'] = ''; in the template.php file, inside your override function (before the callback). Reading this line of code shows us that we identify the field on the form and set its value to '' - nothing. Here is what the function would look like:

// Add Form Start...........jghyde..
if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_event_listing')){
	 function phptemplate_node_form($form) {
	 $form['field_website'] = '';
	 return _phptemplate_callback('event_listing_edit', array('user' => $user, 'form' => $form));
	 }
}
// Add Form End.................
// Edit Form Start...........Dublin Drupaller..
if ((arg(0) == 'node') && (arg(2) == 'edit')){
    $node = node_load(array('nid' => arg(1)));
	    if ($node->type == 'content_event_listing'){
		function phptemplate_node_form($form) {
		$form['field_website'] = '';
		return _phptemplate_callback('event_listing_edit', array('user' => $user, 'form' => $form));
		}
	    }
}
// Edit Form End........

Note that I had to put the code snippet into BOTH the 'Add form' and 'Edit form' sections that I newly added.

The 'not so elegant' way to do it is to add the unwanted fields to your tpl.php file, just like the wanted ones and then simply use CSS 'display: none;' to style it away (see below).

12. OK, now you have a form with all the fields you want on it, none of the ones you don't want and you may even have grouped some of them together into a collapsible group, now what? Now you can style each of those elements using CSS. I am no CSS guru, so I am only doing a few simple things here: 1) I am showing an example of using CSS to hide a field and 2)I am also putting two fields side by side.

To use CSS to hide a field, simply identify the <Div id=> of the field that you want to hide, then create a style in your style.css file for that DIV (or in your custom, linked css file - I think it is recommended that you actually use your own css file so that any modifications you make will survive an upgrade)

Here is an example:

#jpj10 {
	display: none;
}

To use CSS to put to fields side by side, you need to wrap each field that you want side by side in span tags instead of div tags like this:

<span id="jpj8b"><?php print form_render($form['field_phone']); ?></span>
<span id="jpj8c"><?php print form_render($form['field_website']['0']['value']['link']); ?></span>

Then create styles for them to float left like this:

#jpj8b, #jpj8c {
	float: left;
}

[scr005.gif]

Now my two fields will display side by side - I leave it to you to make it look better - this is just the mechanics of getting it to work!

I hope this helps!
(sorry, coulnd't figure out how to include screenshots with the post)

Comments

eliza411’s picture

I really struggled the first time I tried to theme a CCK input form and sure could have used this! I'm looking forward to trying what you've put together in the next few weeks because it goes farther than I did then.

After just reading through what you've written, I wondered if you had any input on the group widget for cck.

I used it to create groups on my input form and was really disappointed they worked there but had no effect on the output. What you're doing to create groups wouldn't affect output grouping either, right?

jpjanze’s picture

Hi eliza411 - no, none of this will affect output...however, the contemplate module is perfect for themeing cck output (and it will create groups)...if you haven't looked at it yet, you should, it is very powerful and very easy!

http://www.harostreetmedia.com

morphir’s picture

Great How-to! Keep up the good work m8!

morphir.com

macm’s picture

thanks a lot

Great diamond and could be in handbook documentation.

Congratulations!

squaretone’s picture

FYI, for those playing around with drupal 5x; replace form_render() with drupal_render()

Thanks for posting this article.

Eric Lawrence
Developer/UX Designer
http://squaretone.com

macm’s picture

Hi

This article works fine. Excelent!!

macm’s picture

I found a bug.

I created my custom form with this tutorial. Ok.

After this I tried edit my content type (Click in edit tab) and I received

Fatal error: Cannot redeclare phptemplate_node_form() (previously declared in C:\wamp\www\mydrupal\themes\bluemarine\template.php:70) in C:\wamp\www\mydrupal\themes\bluemarine\template.php on line 83

my code is

// Add Form Start...........jghyde..
if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_contenttype1')){
	 function phptemplate_node_form($form) {
	 return _phptemplate_callback('contenttype1_edit', array('user' => $user, 'form' => $form));
	 }
}
// Add Form End.................
// Edit Form Start...........Dublin Drupaller..
if ((arg(0) == 'node') && (arg(2) == 'edit')){          
    $node = node_load(array('nid' => arg(1)));
		function phptemplate_node_form($form) {             (ERROR HERE)
          	return _phptemplate_callback('contenttype1_edit', array('user' => $user, 'form' => $form));
		}
}
// Edit Form End........



// Add Form Start...........jghyde..
if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_contenttype2')){
	 function phptemplate_node_form($form) {
	 return _phptemplate_callback('contenttype2_edit', array('user' => $user, 'form' => $form));
	 }
}
// Add Form End.................
// Edit Form Start...........Dublin Drupaller..
if ((arg(0) == 'node') && (arg(2) == 'edit')){           
    $node = node_load(array('nid' => arg(1)));
		function phptemplate_node_form($form) {           (AND TO POINT ERROR HERE)
          	return _phptemplate_callback('contenttype2_edit', array('user' => $user, 'form' => $form));
		}
}
// Edit Form End........


etc... for all mycontenttypes

What I am doing wrong?

jpjanze’s picture

Hi Macm,

As I mentioned in my post, I am no PHP developer! However, it may be that you have to nest some 'if' statements to get it to work for multiple content types? Hopefully a developer will read this and be able to provide better/more feedback.

Again, i hate to give programming pointers, because I am only guessing, but what about something like this?:

// Edit Form Start...........Dublin Drupaller..
if ((arg(0) == 'node') && (arg(2) == 'edit')){ 
               $node = node_load(array('nid' => arg(1)));
               function phptemplate_node_form($form) { 
               if ($node->type == 'contenttype1') {
                             do some stuff here
               }
               elseif ($node->type == 'contenttype2') {
                             do some stuff here
               }
}
// Edit Form End........

Again, this is just a guess from someone who doesn't really know what they are talking about! Dangerous stuff!

Regards
Jon Paul
http://www.harostreetmedia.com

macm’s picture

Didnt work, I will keep trying and if I find a solution I post here. Dont worry I am not a developer too.

But If developers read this post please help us.

We are almost there with a easy way to custom input forms.

Lyal’s picture

Hello there,

What're you doing that's causing an error is redeclaring the same function over and over and over again. A function name exists as an address to point to to execute a set of code.

Let's look at the 4 if statements you have:

1. if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_contenttype1')){
2. if ((arg(0) == 'node') && (arg(2) == 'edit')){
3. if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_contenttype2')){
4. if ((arg(0) == 'node') && (arg(2) == 'edit')){ 

Now, 1 and 3 are different - arg(2) must equal contenttype1 or contenttype2, so the function will never be redeclared on the same page load.

2 and 4 are identical. So long as two remains true, so will 4. What I would do, is remove #2, and with #4 try:

if ((arg(0) == 'node') && (arg(2) == 'edit')){
$node = node_load(array('nid' => arg(1)));

function phptemplate_node_form($form) { 
return _phptemplate_callback($node->type, array('user' => $user, 'form' => $form));
}
}

Let me know if this works for you!

Haro Street Media

macm’s picture

Hi Lyal

If I understand, not yet but "Fatal error" stop. Now Edit page is blank

// Add Form Start...........jghyde..
if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_contenttype1')){
	 function phptemplate_node_form($form) {return _phptemplate_callback('contenttype1_edit', array('user' => $user, 'form' => $form));}}
// Add Form End.................

// Add Form Start...........jghyde..
if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_contenttype2')){
	 function phptemplate_node_form($form) {
	 return _phptemplate_callback('contenttype2_edit', array('user' => $user, 'form' => $form));}}

// Edit Form Start...........Dublin Drupaller..
if ((arg(0) == 'node') && (arg(2) == 'edit')){$node = node_load(array('nid' => arg(1)));
function phptemplate_node_form($form) {
return _phptemplate_callback($node->type, array('user' => $user, 'form' => $form));
}
}

Thanks for help

sepeck’s picture

Could you add it as a child page to the handbook? It would go as a child page here: http://drupal.org/node/22803

-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide -|- Black Mountain

-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide

Zach Harkey’s picture

+handbook

Yes, please add it to the handbook.

-zach
--
harkey design

: z

rjleigh’s picture

See the handbook page comments for an alternative to the template.php part of this!!

warplesnark’s picture

Many thanks for the article - you've helped me a lot.

Couple of additional points others might find useful: if you are using groups of fields, you can output the form for the entire group using something like

<?php print form_render($form[my_group_name]); ?>

To get the description of a group (and then mess around with the fields inside it) I had to do this (not sure if this is the most elegant method)

print $form[my_group_name]["#description"];

To print an element inside a group

 form_render($form[my_group_name][my_field_name][0][value]);

I don't understand how the form tree works ... this was me playing around until I got it to work.

Also, many themes do not have a templates.php - but you can just create an empty one if it does not exist (it should be a php template, i.e. start with a php opening tag).

All this work would have been spared me if cck wrapped each of the label/form elements in a span itself :-) I would like to add this to CCK when I know Drupal better.

brst t’s picture

Can you use this to format a group of fields as a table?

It'd be wonderful if views could be used to customize a cck input form.

lenkkivihko’s picture

Any hints how

  • I could change width of a CCK text field
  • and even position 2 fields on a "same line".

The same line must be doable with tables. But the first one is more tricky.

All hints appreciated. Thanks!

jeff h’s picture

There are two ways to change the width of a CCK text field:

* if you want the width changed on the input page AND on the display (ie everywhere) you should just change the definition of that field from within CCK directly (ie in your site's admin/node/types)

* if you only want to change the width of the field in certain places, use CSS. The width: property will work on text fields.

Hope this helps.

Jeff

trypokaridos’s picture

I'm not a programmer but I'm trying hard :)

My problem is with multiple fields in a group that I want to render separating the labels from the input fields.
my code looks like :

<?php
print t($form['my_group_name']['fieldgroup_table']['0']['my_field_name']['value']['#title']);
unset ($form['my_group_name']['fieldgroup_table']['0']['my_field_name']['value']['#title']);
print drupal_render ($form['my_group_name']['fieldgroup_table']['0']['my_field_name']);
?>

everything is working fine
but when i'm trying to loop the array and render all same fields like :

<?php
for ($x=0 ; $x<=3; $x+=1);

{ 
print t($form['my_group_name']['fieldgroup_table'][$x]['my_field_name']['value']['#title']);
unset ($form['my_group_name']['fieldgroup_table'][$x]['my_field_name']['value']['#title']);
print drupal_render ($form['my_group_name']['fieldgroup_table'][$x]['my_field_name']);
}
?>

drupal renders only the last field ($x=3).

I'm stuck can anybody help ?

Thanks in advance

nevets’s picture

Look at the line

for ($x=0 ; $x<=3; $x+=1);

it ends in a semi-colon, remove that and I think things will work more like you expect. As it is, the loop runs setting $x to 4 (the exit condition for the loop) and then does the print(), unset() and print() lines of code.

tille’s picture

..thanks for this great how-to.. - ..found it looking for some other admin input style questions.. but will definitely have to deal with cck styling in the very near future..:]

greetz, till..

___________________________

macm’s picture

If you have more than one content types the solution is:

// Add Form Start...........jghyde..
if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_contenttype01')){
	 function phptemplate_node_form($form) {return _phptemplate_callback('contenttype01_edit', array('user' => $user, 'form' => $form));}}
// Add Form End.................



// Add Form Start...........jghyde.. repeat this block for each contenttype..
if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_contenttype02')){
	 function phptemplate_node_form($form) {
	 return _phptemplate_callback('contenttype02_edit', array('user' => $user, 'form' => $form));}}
// end block


// Edit Form Start...........Dublin Drupaller and macm..
if ((arg(0) == 'node') && (arg(2) == 'edit')){
$node = node_load(array('nid' => arg(1)));
function phptemplate_node_form($form) {
if ($node->type == 'content_contenttype01'){return _phptemplate_callback($node->type, array('user' => $user, 'form' => $form));}
else if ($node->type == 'content_contenttype02'){return _phptemplate_callback($node->type, array('user' => $user, 'form' => $form));}
else if ($node->type == 'content_contenttype03'){return _phptemplate_callback($node->type, array('user' => $user, 'form' => $form));}
else if ($node->type == 'content_contenttype04'){return _phptemplate_callback($node->type, array('user' => $user, 'form' => $form));}
}
}

Ok I have another tip:

use:

print drupal_render($form['taxonomy']['1']);
print drupal_render($form['taxonomy']['2']);
print drupal_render($form['taxonomy']['3']);

to render your taxonomies where 1,2,3 is the number of your vocabulary.

Now I want insert this taxonomies and create my "dynamic taxonomy form"

like this http://www.ubercart.org/jquery_dynamic_form/18

What I am thinking is explode html elements from print drupal_render($form['taxonomy']['1']); and paste into the code of example above (http://www.ubercart.org/jquery_dynamic_form/18)

I need some help please!

Is it possible?

zigma’s picture

am trying to print individual category.

It's now working for me though.

macm’s picture

Are you creating Dynamic Forms?
If possible, Please let me know your solution

zigma’s picture

No I was just trying to render individual categories to theme them individually.

I gave up.
I am going to use $form['taxonomy'] to theme entire category at one place.

vjuhasz’s picture

print drupal_render($form['taxonomy']['tags'][21]);

where '21' is the vocabulary ID of the category you would like to display.

Carlitus’s picture

If we want to theme the form we don't want to make the final form_render($form). It's better to print only the input we want to show. It's easy to make it, you only need this

print form_render($form['form_token']);
print form_render($form['form_id']);

print form_render($form['preview']);
print form_render($form['submit']);
print form_render($form['delete']);

Neurotic web design

_michel_’s picture

Hi.

Thanks for this "howto" theme CCK input forms.

I have to change the value of variable arg(2) to work correctly

Instead of :

if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_event_listing')){

I have to change to :

if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'event_listing')){

And it works perfectly.
I am using drupal 5.

Regards.
Michel
www.auxe.net

forgestik’s picture

Sorry for the disturbance,

I know this chapter is about theming input forms, but I'm desparate... ;-)

I'm trying to theme the node's output, and specifically, I need to know how to display a specific field value, as well as looping through all the values (although the latter isn't urgent)

sorry again, (little help would be greatly appreciated) thankx ;-)

Charles

sampelo’s picture

thank you. can you please put the node number of the handbook page?

macm’s picture

If you have trouble

see:

http://drupal.org/node/116014

cck tables change.
node_yourcck to content_type_yourcck

mrf’s picture

Quick update for anyone using Drupal 5.

The node_render function has been deprecated and you will get a function not found error message.

References to node_render should be changed to drupal_render.

Everything worked for me as soon as I switched that.

morphir’s picture

MisterMojo’s picture

Is this still the preferred method to theme cck input in Drupal 5.x (noting the change to node_render function) or is there another approach that better utilizes changes / improvements from 4.7 to 5.x releases?

mrgoltra’s picture

subscribing

deadbeef’s picture

AFAIK if you want to disable unwanted form elements when calling

print form_render($form);

instead of

$form['field_website'] = ''; 

one can use:

unset($form['field_website']);
xjm’s picture

Lot to read though here. Hopefully I can solve my other thread using this information:
http://drupal.org/node/141604

:)

strexy’s picture

hello,
I have followed all the steps of this tutorial and it works fine for a normal cck content type. What about a cck content type with Node Relativity to another cck content type? It seems ignore the IF statement in template.php for this kind of content types. Any suggestions? Thanx.

|strexy

CleanCutRogue’s picture

I've been looking everywhere to try to figure out how to theme the input of forum topics, and this finally gave me what I needed. I wanted to simply remove a few things from the edit page - for example, I don't want users to be able to select which parent they want to post their forum topic in... just default to wherever they are when they click "New". I did it using this method.

in my template.php file:

if (arg(0) == 'node' && arg(1) == 'add' && arg(2) == 'forum'){
  function phptemplate_node_form($form) {return _phptemplate_callback('forum_edit', array('user' => $user, 'form' => $form));}
}

if (arg(0) == 'node' && arg(2) == 'edit'){
  $node = node_load(arg(1));
  if ($node->type=='forum') {function phptemplate_node_form($form) {return _phptemplate_callback('forum_edit', array('user' => $user, 'form' => $form));}}
}

then I created a file called 'forum_edit.tpl.php' in the same directory on my server as 'node.tpl.php' etc. that looks like this:

<DIV ID="title"><?php print drupal_render($form['title']); ?></DIV>
<DIV ID="body"><?php print drupal_render($form['body_filter']); ?></DIV>
<DIV ID="buttons"><?php print drupal_render($form['preview']) . ' ' . drupal_render($form['submit']); ?></DIV>
<?php if (!user_access('administer forums')) print '<DIV ID="hiddenstuff" style="display:none;">'; else  print '<DIV ID="adminstuff">';?>
<?php print drupal_render($form); ?></DIV>

This way, if you have permission to administer forums, you'll get all the other stuff. Otherwise you'll just get "subject", "body", "preview", and "submit". :-) and I didn't really theme it-- just hid some stuff, all without a hack or any css!!

HarisH04’s picture

Hello this is harish . i tried this theming CCK input forms in drupal 5 , it was a very cool option for theming the cck forms. But i have a problem in that. I am not able to theme or relocate the individual fields in my cck form . I am able to theme only the groups and the default fields like TITLE and BODY . I am not able to retrieve or relocate user-defined fields like CITY,STATE etc...
I used this piece of code..
It works partially (For groups and default fields (title,body).

<DIV ID="title"><?php print drupal_render($form['title']); ?></DIV>
<DIV ID="email"><?php print drupal_render($form['email']); ?></DIV>
<DIV ID="buttons"><?php print drupal_render($form['preview']) . ' ' . drupal_render($form['submit']); ?></DIV>
<?php if (!user_access('administer forums')) print '<DIV ID="hiddenstuff" style="display:none;">'; else  print '<DIV 

ID="adminstuff">';?>
<?php print drupal_render($form); ?></DIV>

The Second Field is the User-defined field "EMAIL" which is not showing up for theming.
Please anybody solve my problem....
Thanx.

nevets’s picture

Try adding to the start of the file

<?php print '<pre>' . print_r($form, TRUE) . '</pre>'; ?>

which will show you all of the elements of $form

CleanCutRogue’s picture

I've been looking everywhere to try to figure out how to theme the input of forum topics, and this finally gave me what I needed. I wanted to simply remove a few things from the edit page - for example, I don't want users to be able to select which parent they want to post their forum topic in... just default to wherever they are when they click "New". I did it using this method.

in my template.php file:

if (arg(0) == 'node' && arg(1) == 'add' && arg(2) == 'forum'){
  function phptemplate_node_form($form) {return _phptemplate_callback('forum_edit', array('user' => $user, 'form' => $form));}
}

if (arg(0) == 'node' && arg(2) == 'edit'){
  $node = node_load(arg(1));
  if ($node->type=='forum') {function phptemplate_node_form($form) {return _phptemplate_callback('forum_edit', array('user' => $user, 'form' => $form));}}
}

then I created a file called 'forum_edit.tpl.php' in the same directory on my server as 'node.tpl.php' etc. that looks like this:

<DIV ID="title"><?php print drupal_render($form['title']); ?></DIV>
<DIV ID="body"><?php print drupal_render($form['body_filter']); ?></DIV>
<DIV ID="buttons"><?php print drupal_render($form['preview']) . ' ' . drupal_render($form['submit']); ?></DIV>
<?php if (!user_access('administer forums')) print '<DIV ID="hiddenstuff" style="display:none;">'; else  print '<DIV ID="adminstuff">';?>
<?php print drupal_render($form); ?></DIV>

This way, if you have permission to administer forums, you'll get all the other stuff. Otherwise you'll just get "subject", "body", "preview", and "submit". :-) and I didn't really theme it-- just hid some stuff, all without a hack or any css!!

scoutr’s picture

When entering the code to list the available arrays, it wouldn't work with "<code></code>", I had to use the following in Drupal 5.1:

<?php
  print "<pre>";
  print_r(array_values($form));
  print "</pre>";
?>

Not sure if this is due to my browser or not. Hope this helps.

barako’s picture

Hi,

Thanks so much for this tutorial which helped me a lot.
But I've still a problem with the display of cck labels.
I would like to not display them.
But in my file tpl.php I just wrote for example :
<div id="oliv"><?php print drupal_render($form['field_contenu']); ?></div>
And in my form, Drupal displays the label, the textbox and the help text.
All I want is to hide label.

Could someone help me please ?

Thanks

krwester’s picture

This is perfect, exactly what I have been looking for. However, could someone help me out with the following fields which don't seem to follow the standard format.

1. I want to be able to add the image field (using the image module image hook available for all content)
2. I also want to be able to add the "upload attachment" field.

I'm unsure of the general format for these. Any help would be appreciated.

Thanks!

smoothstr@drupal.org’s picture

The original poster said that they wanted to change the order on the input forms. This is done using the manage fields tab in content type. Change the weight of a field, and you change the order that they appear in on the input form and the output.

Jeff

smoothstr@drupal.org’s picture

And in reply to images: use the imagefield module to attach images. Set up a field for images, use multiple if you want to let people upload more than 1 image per node. Also set the display properties to hide the field title on the node otherwise you get an ugly field name like 'Picture:' just above the picture. Most people reading don't need telling that it's a picture unless it's a very specific picture like 'Wound entry point:'

Jeff

ms1’s picture

Hi

I am working with drupal 5.2. I tried to follow your suggestions to hide some fields in my customized node creation page. But unfortunately got stuck in the first place.

Here is what I did,

I created a file called edit_user_video.tpl.php in which I put the yahoo test code, i.e.

<?php
print("yahoo, it works!"); 
?>

Then I created a template.php file (since bluemarine theme does not have one) and added the following code:

<?
if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_type_user_video')){
function phptemplate_node_form($form) {
return _phptemplate_callback('edit_user_video', array('user' => $user, 'content' => $form));
}
}
?>

and then tried to look at the submit page, but the yahoo message never came.

Since I am new to PHP, I really don't know much. Maybe I am thinking their is some issue with the use of "$form" variable, since I did not find it anywhere.

(Note:- I also tried naming a file as 'page-node-add-user-video.tpl.php' and could thus achieve that 'yahoo' page. But then using the code for printing the variables did not work and returned empty. I used:

<?php
print "<code>&quot;; print_r(array_values($form));print &quot;

";
?>

I again suspect the $form variable )

Please help out, as I already spent a full night on this issue, where I seem to be missing something fundamental.

Thanks

nevets’s picture

The check against arg(2) in Drupal 5 should use the name of your content type, I am guessing that should be 'user_video'. You can check this by going to create content and creating a new instance of your content type. Look at the part after 'node/add/', that is what you want to check for.

Also, you may want to check out CCK Field Permissions which makes it possible to limit access to field without any coding/theming.

ms1’s picture

Hi Steve

Loads of thanks for your help. Changing arg(2) resolved the issue. But still I have the problem with the display of the elements, i.e.

print "&amp;quot;; print_r(array_values($form));print &amp;quot;";

only gives the output as <"; print(array_values(Array));print ". But the field elemts of the array are not printed as was expected w.r.t the article.

----------------------

Also I already tried CCK Field Permission module. But my requirement is to hide two input fields from users (the input fields being prepopulated). What happens is that when I do not give view-permissions to the user for those two fields, they actually are not added at all and are missing in the created node. So I thought it was not appropriate.

----------------------

Can you please tell me how to get the fields available with the forms (since the given commands are not working)

Thanks

nevets’s picture

Try this

<?php
print '<pre>' . print_r($form, TRUE) . '</pre>';
?>
ms1’s picture

Hi again Steve.

I tried the piece you provided, but it returns a blank box. No progress yet, but I am trying lets see.

Thanks & Regards

Heine’s picture

(arg(2) == 'content_type_user_video')

I don't think arg(2) (which is the third part of the URL) equals this value.

--
The Manual | Troubleshooting FAQ | Tips for posting | How to report a security issue.

ms1’s picture

Yes, I already fixed that, after Nevets pointed out. I changed it to 'user-video' and it started working, but only the first step. (i.e. connecting my new file to be rendered on the submit page).

Now I am unable to use the command (which is mentioned in this post), to display the elements of the form, i.e.

<?php
print "<code>&amp;quot;; print_r(array_values($form));print &amp;quot;

";
?>

which I need to know in order to hide them.

Regards

Heine’s picture

Sorry.

You have an emtpy $form variable because you stuff it in $content, not $form with:

return _phptemplate_callback('edit_user_video', array('user' => $user, 'content' => $form));

--
The Manual | Troubleshooting FAQ | Tips for posting | How to report a security issue.

ms1’s picture

Actually that was typo, that I had already corrected. (I had changed it to form).

-----------
Although I found an alternate solution to hiding the fields in the cck content type, i.e. by using the formfilter module. (Well I am unsure about its stability since it is in development phase). It is very straight and simple.
-----------

But I still want to know that how to get the form variables printed, and why is this code not working.

Thanks & Regards

Heine’s picture

print "&amp;amp;quot;; print_r(array_values($form));print &amp;amp;quot;";

Is this actual code or also a typo?

Try

print  '<pre>'. check_plain(print_r($form, TRUE)) .'</pre>';

--
The Manual | Troubleshooting FAQ | Tips for posting | How to report a security issue.

ms1’s picture

Sorry for the first one but this was not a typo.

Well I even tried what you mentioned, but did not work. The output is just a single line, blank box.

I think I will start from beginning so see whats wrong..

Thanks

Heine’s picture

I suggest to create the following function in template.php:

function phptemplate_user_video_node_form($form) {
  print  '<pre>'. check_plain(print_r($form, TRUE)) .'</pre>';
}

And see what happens.
--
The Manual | Troubleshooting FAQ | Tips for posting | How to report a security issue.

ms1’s picture

Thanks a million for your time and effort. It worked perfectly this time. I got some faith back.

By the way, I believe you you used the function name such that it directly related to the page. But is there anything we can understand as to why the previous code was not working?

Thanks & Regards

liquidcms’s picture

Perhaps i am missing something here - but if the CCK module added DIVs around its form elements (which it doesnt do - but couldnt be too hard to add??) wouldn't this all become simply a CSS task and about 10 times simpler than the procedure here?

So for type "event_listing" with fields "body" and "data" we get something like the DIVs:

<div id="event_listing" class="cck_input_form"> - around entire form
<div id="event_listing-body" class="cck_input_form_item"> - around entire body element
<div id="event_listing-body-label" class="cck_input_form_label"> - around label for body field
<div id="event_listing-body-input" class="cck_input_form_input"> - around input for body field

.. etc...

but this does seem a bit to simple to be correct????

This doesn't deal with filling values, removing field or anything else that form_later would be required to do - but it does give you the ability the theme the input form.

Perhaps one flaw in this is that unless you do absolute positioning in your CSS it is difficult to re-order your fields - but then why not just put them in the correct order to start with.

Peter Lindstrom
LiquidCMS - Content Management Solution Experts

nevets’s picture

Actually the form already has an ID so you can already achieve alot with just CSS as you have pointd out.

liquidcms’s picture

but if the fields don't have ID's there really isn't that much you can do... however i figured i'd pursue my little idea a bit further and found that this simple change of 1 line gives ID's to all the form elements:

in the function theme_form_element (in form.inc) changing the first line to:

$output  = '<div id="'.$element['#id'].'" class="form-item">'."\n";

now gives ID's to all form elements

So with this you can now use just CSS to format and arrange the form elements on your input form.

The only issue i see with this is that the $element['#id'] value is not very unique - ideally there would be a DIV wrapped around the entire form and then you could, for example format the "title" field of "content-nodetype-x" different than the "title" field of "content-nodetype-y". Although as nevets points out the form itself has an ID and i am not much of a CSS expert but you could likely use that to be more specific about which field you are styling.

ALSO - again unless i am REALLY missing the point here - this minor tweak should be added to the core code - but failing that it would be possible to simply redefine theme_form_element in template.php and override this omission.

so for my little test node type input form, all that was required (after the 1 line form.inc change) was this in my style.css

#edit-field-client-uids  {float:left; width:200px; margin-right:50px}
#edit-title {float:left; width:300px}
#edit-field-staff-uids {float:left; width:200px; margin-right:50px; clear:left;}
#edit-field-hours-0-value {float:left; width:300px}
#edit-field-details-0-value {float:left; width:600px; clear:both;} 
#edit-field-status-0-value {float:left; width:200px; clear:both;}

and i now had a form with sets of input fields side by side rather than all vertically arranged.

pretty sure this is much simpler than what is being suggested here.

Peter Lindstrom
LiquidCMS - Content Management Solution Experts

mindlace’s picture

As far as I can tell, all the form elements in my drupal 5.2/cck 1.6 install do have IDs. Even if they didn't, you can use the descendant child selector to pick them from a form with IDs. This doesn't cover needing to change scripting.

liquidcms’s picture

ok, well granted i don't know CSS THAT well but this is what have for a renamed "title" field for a cck node input form:

<div class="form-item">
    <label for="edit-title">Product Name:<span class="form-required" title="This field is required.">*</span></label>
    <input id="edit-title" class="form-text required" type="text" value="" size="60" name="title" maxlength="128"/>
</div>

so if i wanted to simply move the entire field say to the right i would want to move the DIV which is wrapped around the ENTIRE field (i.e. label and input field) and this has no ID - so i think hard to do???

Peter Lindstrom
LiquidCMS - Content Management Solution Experts

wolfderby’s picture

Can you give an example of "the descendant child selector" I've never heard of that and don't know what it is?

I'm looking to hone in on specific fields within the form_id "node-form"

or to even assign the fields their own specific form_id

mixey’s picture

Bookmarking!

grp’s picture

Hi. Thanks for the great tutorial.

I'm curious about one thing....is there something wrong at my end that's stopping me from seeing the screencaps, or did the author just never get around to placing them in?
I keep seeing code like the following: [screenshot of 'yahoo it works' scr002.gif] ... but no images.

Still a very useful tutorial, but as I didn't see anyone else asking this question, I just had to know.

thanks.

jpjanze’s picture

Sorry about the lacking images.... I have them, but at the time I posted this, I didn't have a means of posting them in the article...I will try to get some time over the holidays and figure out how to post them!

Cheers!
Jon Paul

http://www.harostreetmedia.com

STyL3’s picture

+1

baloneysammitch’s picture

I've modified my form using a tpl page and correctly themed it, duplicating all fields. It functions just fine, until I try to add a captcha. I can't find the code I need to render the captcha into my modified form. Has anyone been able to do this?

Heine’s picture

You need to print the output of drupal_render($form) at the very end.
--
The Manual | Troubleshooting FAQ | Tips for posting | How to report a security issue.

Guddie’s picture

Hi,

how to change the width of the text field and bring the label and the corresponding text fields inline,.. i.e in front of each other.

suoko’s picture

Hi,

I have problems with position of 'submit' and 'preview' buttons as well as with appearance of 'delete' button

This is my mynode_edit.tpl.php code:

print drupal_render($form['title']);
print drupal_render($form['body_filter']);
print drupal_render($form['taxonomy']);
print '<span id="cck_table">' . drupal_render($form[group_dati_extra]) . '</span>';
print '<span id="cck_table">' . drupal_render($form[group_dati_immobile]) . '</span>';
print '<span id="cck_table">' . drupal_render($form[group_dati_generali]) . '</span>';
print '<span id="cck_table">' . drupal_render($form[group_immagini]) . '</span>';
print '<span id="cck_table">' .  drupal_render($form['submit']) . '</span>';
print '<span id="cck_table">' .  drupal_render($form['preview']). '</span>';
print '<span id="cck_table">' .  drupal_render($form['delete']). '</span>';

and this is the code in the style.css:

#cck_table {
 float: left;
}

With this code I end up with correctly aligned groups and 'submit' and 'preview' buttons are placed on the right of the latest group.
'Delete' button isn't shown at all.

I tried changing the float css for the buttons in order to have them at the BOTTOM of the page with no success.
Any suggestions?

Here is a screenshot of my input form:
http://picasaweb.google.com/gabriele.vidali/WebDeveloping/photo#51698359...

thanks

baronmunchowsen’s picture

This is fantastic - thank you very much

rjdempsey’s picture

I simply need to change the submit button value. It was suggested here: http://drupal.org/node/140387 that making a small module was the correct way to do it. That's seems like a bit much just to change the value on one button. What is the simplest way to do this?

baronmunchowsen’s picture

I suppose to change all of the submit button values you could use:

function YOUR_THEME_NAME_submit($element) {
  $element['#value'] = 'YOUR SUBMIT TEXT';
  return theme('button', $element);
}

in your template.php file...?

SocialNicheGuru’s picture

I think I'll have to use this now.

http://SocialNicheGuru.com
Delivering inSITE(TM), we empower you to deliver the right product and the right message to the right NICHE at the right time across all product, marketing, and sales channels.

jjjames’s picture

Does this still apply to Drupal 6? Good info none the less.

bdawg8569’s picture

I would also like to know if this applies to drupal 6. I have not been able to get it to work, but that doesn't necessarily mean anything. Anybody know for sure if it works?

wfx’s picture

Subscribe