How to use custom #theme function for a set of fields in a drupal module?
I have a module that creates a form that contains a set of fields. Rather than using an element <legend>
to render the header of a fieldset, I want to place that content in an element <div>
. But I only want to change the behavior for the form returned by my module, so I do not want to post any new functionality in the theme.php file of the theme.
In mymod.module I have defined:
// custom rendering function for fieldset elements
function theme_mymod_fieldset($element) {
return 'test';
}
// implement hook_theme
function mymod_theme() {
return array(
'mymod_fieldset' => array('arguments' => array('element' => NULL)),
'mymod_form' => array('arguments' => array())
);
}
// return a form that is based on the 'Basic Account Info' category of the user profile
function mymod_form() {
// load the user profile
global $user;
$account = user_load($user->uid);
// load the profile form, and then edit it
$form_state = array();
$form = drupal_retrieve_form('user_profile_form', $form_state, $account, 'Basic Account Info');
// set the custom #theme function for this fieldset
$form['Basic Account Info']['#theme'] = 'mymod_fieldset';
// more form manipulations
// ...
return $form;
}
When my page was rendered, I expected to see the field set representing "basic credentials" being completely replaced by the test message "test". Instead, what happens is that the elements <fieldset>
and <legend>
displayed as normal, but instead of the body of a set of fields is replaced by a test message, for example:
<fieldset>
<legend>Basic Account Info</legend>
test
</fieldset>
Why doesn't my #theme function have the ability to replace the entire element <fieldset>
? If, instead, I placed a textbox in this function, I was able to completely replace the element <input>
along with its label. Also, if I provide an override in my site template.php for the theme_fieldset, it works as expected and I can replace it completely <fieldset>
, so I know it is possible.
How is #theme different from fields in a module?
a source to share
Have you tried overriding theme_fieldset () instead of using the #theme function? I believe you could do something like this in your .module file:
function mymodule_fieldset($element) {
// do something;
return $html;
}
This applies to all field sets. You can do some kind of validation on $ element for the fields you want to affect, and then use the default implementation for all the others.
Take a look at: http://api.drupal.org/api/function/theme_fieldset/6
I know this is an old post, but I faced the same problem. I came up with an ugly job. This is definitely a bug in the Forms API. Perhaps my workaround will be helpful to someone.
I found (and added) a bug report here: http://drupal.org/node/225698
It's worth checking that before attempting my hacky fix.
I'm not sure if the children are in $form['Basic Account Info']
this example, but basically what you can do is use a drupal_render()
fieldset for those children, and then recreate an array of field arrays other than $form['Basic Account Info']
, subject it s theme()
and pass it to the form array as markup.
$fieldsetElement = array(
//$child is the key of whatever child you need in the fieldset
//you may have to alter this for multiple children, stringing
//together multiple drupal_render calls on each children
//(#children needs to be a string.. unless your theme can handle the array)
'#children'=>drupal_render($form['Basic Account Info'][$child]),
'#attributes'=>array(),//set real attributes
'#title'=>$form['Basic Account Info']['#title']
);
$form['Basic Account Info'] = array(
'#type'=>'markup',//not really needed, is default
'#value'=>theme('mymod_fieldset',$fieldsetElement)
);
a super-duper hack is probably causing a disconnect with form state and potential validation failure - but both can be fixed by trial and error using the form api. I wouldn't recommend this unless you really want to get your hands dirty with PHP and drupal API, but this is really the only way if you can't live without variable fields in your module ... Maybe try prefixing and suffix?
a source to share
Your code concept works, meaning you can do what you want.
There are some things that might explain why this doesn't work.
- The field set is not
$form['Basic Account Info']
. - The cache needs to be cleared.
- $ form ['Basic account information'] ['# theme'] is lost / redefined later when the code is executed.
Try to take a look at $form
before doing any of the moderations. When I tried to copy the code, I ran into the error:
- User.pages.inc file must be loaded
a source to share