In this blog post we will show you how to allow content editors to edit similar but different "pages" in Drupal, all based on a shared content type without confusion, by hiding the unnecessary form elements.
There can be times when you wish to create several similar content types that only differ slightly from one another (perhaps by a field or two). Let’s take a website that posts environmental warnings on different types of pollution as an example. The site could report air pollution, water pollution and ground pollution warnings. One option is to create 3 separate content types, one for each type of pollution. Air pollution may have an air quality index field, while ground pollution may have a field that shows how it affects the property value of nearby buildings. The point here is that most of the fields for all 3 content types are the same. Discovery Date, Detail Review, Severity, and so on. An alternative implementation is to use one content type called Pollution and a field in that content type named ‘Pollution_type’. This field in the content type would allow us the flexibility to know what type of pollution we are dealing with.
The problem comes when an environmental investigator wishes to add a new air pollution warning. They will see a Drupal form with a ground pollution area field, land value field and all the other fields which are not related to the air pollution type. This can make the user interface crowded with unrelated fields, and unusable. So how can we have one content type and one form which adapts to the type of pollution a user has selected?
Simple.
By overriding the node_form.tpl file in the themes directory for the ‘pollution’ node type, we can take full control of the appearance of our form. We can then add some JavaScript, or better yet JQuery, which will hide and show elements based on which review type the user has chosen.
Step 1: Set Up CCK Fields
To set this example up we need a simple CCK content type with the following fields (please see Drupal documentation about how to create CCK fields):
Review_ type : drop down with default fields: ( 1 – air, 2 – ground, 3 – water)
hazard_time (text box)
area_affected (text box)
warning_date (date)
warning_details (text area)
etc ...Step 2: Override the Node Form for the Review Content Type
To do so you need to create a function in the template.php file (which will be found in your themes directory). The name of the function will need to take on the following form:
phptemplate_[content_type]_node_form() and in our case the function will look like the following:
function phptemplate_pollution_node_form($form) {
drupal_add_js('sites/all/modules/js/pollution.js');
// Add JQuery to act on the form
// load the review_node_form.tpl.php file to render this
//form.
return _phptemplate_callback('pollution_node_form',
array('form' => $form));
}
The reason why this works is because when Drupal processes the form for a particular node that has been queued up to render, it will search through the template.php file for a function in the form of phtemplate_[content_type]_node_form: If it finds one it will then load and render the form returned by this function.
Step 3: Render a Custom Form
In the themes directory you need to create the form theme function that is returned by the function in the template.php function. In our example this would be pollution_node_form.tpl.php
Now in the pollution_node_form.tpl.php file we create the HTML and attributes we need to render the form. This includes any tags and classes that will help us when we use JQuery to hide and show the form.
<?php>
<legend> Type And Title </legend>
<?php echo drupal_render($form['field_pollution_type']); ?>
<?php echo drupal_render($form['title']); ?>
<div id=’warning’>
<?php echo drupal_render($form['field_warning]); ?>
</div>
<div id= 'land_pollute_field’>
<?php echo drupal_render($form['field_land_area_affected
]); ?>
</div>
<div id= ‘air_pollute_field’>
<?php echo drupal_render($form['field_direction_of_
movement]); ?>
</div>// render other field from the CCK content type ..
<?php>
// Unset form elements that you don’t want rendered
unset($form['attachments']);
unset($form['menu']);
…
// Render the rest of the form …
echo drupal_render($form);?>
Now to get the JQuery to connect with the HTML id’s of each separate div we add the following JQuery file to the JavaScipt file referred to in Step 2. In our example the file should be named warning.js and be in the /themes/yourtheme/js directory.
$(document).ready( function() {
// Need to initialize on page load which fields are shown on the page.
$("#land_pollute_field").css("display","block");
$("#water_pollute_field").css("display","none");
$("#air_pollute_field").css("display","none");
var choice = $("#edit-field-pollution-type").val();
// You will need to find the ‘id’ of the dropdown list
switch(choice) {case “land":
$("#land_pollute_field").css("display","block");
$("#water_pollute_field").css("display","none");
$("#air_pollute_field").css("display","none");
break;
case "air":
$("#water_pollute_field").css("display","none");
$("#land_pollute_field").css("display","none");
$("#air_pollute_field").css("display","block");
break;
case "water":$("#land_pollute_field").css("display","none");
$("#water_pollute_field").css("display","block");
$("#air_pollute_field").css("display","none");break;
});
From here its easy to expand the form and manipulate the layout as needed.
Comments