开发者

How do I use a custom #theme function to a fieldset in a drupal module?

I have a module that builds a form that includes a fieldset. Instead of using the <legend> element to render the fieldset title, I want to place this content in a <div> element instead. But I want to change the behavior only for the form returned by my module, so I don't want to place any new functionality into my theme's template.php 开发者_C百科file.

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's 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 gets rendered, I expected to see the fieldset representing 'Basic Account Info' to be wholly replaced by my test message 'test'. Instead what happens is that the <fieldset> and <legend> elements are rendered as normal, but with the body of the fieldset replaced by the test message instead, like this:

<fieldset>
  <legend>Basic Account Info</legend>
  test
</fieldset>

Why doesn't my #theme function have the chance to replace the entire <fieldset> element? If I wrap a textfield in this function instead, I am able to completely replace the <input> element along with its label. Furthermore, if I provide an override in my site's template.php for theme_fieldset, it works as expected and I am able to completely replace the <fieldset>, so I know it is possible.

What's different about providing #theme functions to fieldsets inside a module?


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 would apply to all fieldsets. You could do some kind of check on $element for the fieldsets you want to affect and then use the default implementation for all others.

Take a look at: http://api.drupal.org/api/function/theme_fieldset/6


I know this is an old post -- but I've run into the same issue. I came up with an ugly work around. This is definitely a bug in the Form API. Maybe my temporary fix will be helpful to someone.

I found (and appended) a bug report here: http://drupal.org/node/225698

Worth checking that before trying my hacky fix.

I'm not sure what the children are in $form['Basic Account Info'] in this example, but basically what you can do is use drupal_render() on that fieldset's children, and then recreate a fieldset array separate from $form['Basic Account Info'], theme it with theme() and pass it back 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)
);

super-duper hacking, likely causes disconnect with form state and potential validation failure -- but both are fixable by trial and error with the form api. I wouldn't recommend this unless you really want to get your hands dirty with PHP and drupal form API, but that's really the only way, unless you can live without variable fieldset themes in your module... Maybe try prefix and suffix?


This is just off the top of my head but maybe the difference is because a fieldset is not a form element but just a seperator or a grouper, if you will. Maybe the #theme callback is only for form elements?


The concept of your code works, meaning you can do what you want to do.

There are some things that can explain why it doesn't work.

  • The fieldset is not $form['Basic Account Info'].
  • Need to clear cache.
  • $form['Basic Account Info']['#theme'] is lost/overridden later in the code execution.

Try to take a look at $form before you do any of the moderations. When I tried to copy your code I run into a bug:

  • user.pages.inc file needed to be loaded


I was having the same issue.

You need to use #theme_wrappers instead of #theme

'#type' => 'fieldset',
'#theme_wrappers' => array('mymodule_fieldset'),
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜