New Media Design

Blogs

Drupal - How to Theme CCK Input forms

Originally posted on Drupal Forums
Also added to Drupal Handbook

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')
  2. 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 stylesheets (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 (http://www.harostreetmedia.com) - thanks for emailing code snippets in the middle of the night. Dublin Drupaller - 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. Nick Lewis - whose website is full of helpful and insightful Drupal information.

Now on with the show.

How do you theme a CCK input form?

Assumptions

  • You understand a little CSS (how it works, how you use class= and id= in HTML tags to style the output)
  • 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)
  • 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)

Steps

Step 1: Create your CCK content type
Step 2: Create a [yourcontenttype].tpl.php file
Step 3: Modify template.php
Step 4: 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), then 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 's.

Step 1: Create your CCK content type

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

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

Step 2: Create a [yourcontenttype].tpl.php file

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.

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!"); ?>

Step 3: Modify template.php

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)

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:


<?php
// 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).

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.

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 (Tip from goose2000 for outputting data into a nicer format)

<?php
print("yahoo, it works!");
print("");
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:
<?php ['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:

<?php print form_render($form['field_website']['0']['value']['link']); ?>

(I have wrapped the line in a 'div id=' tag so I can style it using CSS)

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

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

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

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

Contact Info
<?php print form_render($form['field_name']); ?>
<?php print form_render($form['field_email']); ?>
<?php print form_render($form['field_phone_0']); ?>
<?php print form_render($form['field_website']['0']['value']['link']); ?>
<?php print form_render($form['field_description']); ?>

This will look like:

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 <?php $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:

<?php
// 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).

Step 4: Modify style.css

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 ID of the field that you want to hide, then create a style in your style.css file for that (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 tags instead of tags like this:


<?php print form_render($form['field_phone']); ?>
<?php print form_render($form['field_website']['0']['value']['link']); ?>

Then create styles for them to float left like this:


#jpj8b, #jpj8c {
float: left;
}

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!

Additional information

FYI, for those playing around with Drupal 5.x; replace form_render() with drupal_render() - thanks to ericelbow.

Web 2.0.....what is it anyway?

What does it mean to us, well, what does it (or should it) mean to you?
Web 2.0 represents a new shift in the usefulness of the internet and internet applications. It is not revolutionary moment in time marked by a particular event or product launch; rather it is an evolution marked more by the dogged efforts of many individuals and groups across the internet to make it BETTER.

Don't get me wrong web 1.0 is still around and will be for much longer, it's just that web 2.0 is finally hitting the mainstream.

Most mainstream users won't know they are now 'web 2.0 enabled', they will just eventually figure out that what they are doing is now 'easier, faster, better' or that some new functionality is now available, some creative new idea has finally landed.

Now what exactly does 'better' mean? well it has meant different things to different contributors, not just cool new technology for technologies sake - AJAX, RUBY, SOAP/REST etc. but what the cool new technology can do.

To some it has meant a drive to provide a better user experience, an interactive one, whereby readers become contributors and collaborators.

Think of the advent of blogging as the perfect example, not only has blogging brought publication to the masses, it has also made online communication a public two-way process - the essence of blogging is that it allows a community of readers to add feedback, insights, comments, praise and even criticism to the writings of others in their community. It is a collective validation and growth of information that in a web 1.0 world would have been entirely one way, from the writer to the masses.

It is not just the advent of blogs that makes it Web 2.0, it is the way we now use blogs and their prevalence; it is the fact that many now aggregate blogs and then search them to get a 'pulse' on any given topic, we gain insight and understanding of how an entire community or population feels at any given moment about just about anything and then contribute our own insights.

The collective reaction to each new additional insight acts like an 'arbiter' reflecting the current temperament of the entire community! go to boardtracker.com and search any topic, you will find any number of discussions going on across a universe of discussion groups.

To others, it has meant making the user experience of Internet applications better, making internet applications work by the same rules as non-internet applications.

Have a look at Google Maps, a prototypical example of an 'AJAX' implementation - a programming method combining several pre-existing programming technologies into one method - that allows users to interact with a webpage, make changes to the content, all without any screen refreshes (click and drag the map - the map moves!).

In a web 1.0 world, you would have clicked an area of the map, the screen would have refreshed as your request for an updated view of the map was processed and a few moments later a new 'map' would be displayed showing the new map location.

Many of you are probably saying, 'yeah, so what?' The 'so what' is that we are finally at a place when even internet applications can work the way they should have, the way we expect them to (thus, 'yeah so what?' - we have always expected them to act this way!).

To others still it has meant making available and using information machine to machine instead of between people and machines.

In a Web 1.0 world, information owners are publishers of data - they make information available to real people - think of an online news provider (sample.com) or an online map provider mapquest.com - people visit these websites and look up information which is displayed to them in a webpage.

In a Web 2.0 world these same information owners are not only publishers, but are now also sharers of information, allowing other software programs to extract data without any user interaction. Think of an online rental housing directory that collects, stores and displays information about rental property that pulls map information from an online map provider and displays street level maps of the rental property as the viewer looks at each property listing. Have a look at rentalmonster.com for a real-life example of just this!

Today, these are known as 'mash-ups' - there are countless opportunities for 'mashups' - most at the start will involve probably only one 'third party' data source - look at rentalmonster.com for an excellent example - but in the future there will be new and interesting products created by combining multiple disparate data sets into a single application.

In essence owners of data are relinquishing ownership to some degree in HOW their information is being used, allowing for ever more useful applications to be created (in some cases, in a not so 'helpful' way, look at the case of public figure A having their personal residence easily identifiable on a map)

Some have gone so far as to suggest that web 2.0 has meant it is time for a Business 2.0 - a new model of business to accommodate a web 2.0 world - see Early Stage VC of Peter Rip, Managing Director of Leapfrog Ventures, for a more detailed discussion.

In summary, Web 2.0 is an evolution, not a revolution, it is about making the existing internet world work better, not so much different, just better. It is evolutionary, because most users won't even know that the transition has happened, it will just somehow seem easier, simpler, faster and better!

Domain Registration

Syndicate

Syndicate content