如何对 drupal 模块中的字段集使用自定义 #theme 函数?

发布于 2024-08-31 01:41:32 字数 1687 浏览 9 评论 0原文

我有一个模块可以构建包含字段集的表单。我不想使用 元素来呈现字段集标题,而是想将此内容放置在

元素中。但我只想更改模块返回的表单的行为,因此我不想将任何新功能放入主题的 template.php 文件中。

在 mymod.module 中,我定义了:

// 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;
}

当我的页面被渲染时,我期望看到代表“基本帐户信息”的字段集被我的测试消息“test”完全替换。相反,发生的情况是

元素正常呈现,但字段集的正文被测试消息替换,例如this:

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

为什么我的 #theme 函数没有机会替换整个

元素?如果我在此函数中包装一个文本字段,我就可以完全替换 元素及其标签。此外,如果我在网站的 template.php 中为 theme_fieldset 提供覆盖,它会按预期工作,并且我能够完全替换
,所以我知道这是可能的。

向模块内的字段集提供 #theme 函数有什么不同?

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 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

二智少女 2024-09-07 01:41:32

您是否尝试过重写 theme_fieldset() 而不是使用 #theme 函数?我相信您可以在 .module 文件中执行类似的操作:

function mymodule_fieldset($element) {
  // do something;
  return $html;
}

这将适用于所有字段集。您可以对您想要影响的字段集对 $element 进行某种检查,然后对所有其他字段集使用默认实现。

看一下: http://api.drupal.org/api/function/theme_fieldset /6

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

温柔少女心 2024-09-07 01:41:32

我知道这是一篇旧帖子 - 但我遇到了同样的问题。我想出了一个丑陋的解决办法。这绝对是 Form API 中的一个错误。也许我的临时修复会对某人有所帮助。

我在这里找到(并附加)了一个错误报告: http://drupal.org/node/225698

值得在尝试我的黑客修复之前检查一下。

我不确定此示例中 $form['Basic Account Info'] 中的子项是什么,但基本上您可以做的是使用 drupal_render() fieldset 的子级,然后重新创建一个与 $form['Basic Account Info'] 分开的 fieldset 数组,使用 theme() 为其设置主题,并将其传递回表单数组,如下所示标记..

$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)
);

超级骗子黑客攻击,可能会导致与表单状态断开连接以及潜在的验证失败——但这两者都可以通过表单 api 的反复试验来修复。我不会推荐这个,除非你真的想亲自接触 PHP 和 drupal 表单 API,但这确实是唯一的方法,除非你可以在模块中没有可变字段集主题……也许尝试一下前缀和后缀?

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?

橪书 2024-09-07 01:41:32

这只是我的想法,但也许区别在于字段集不是表单元素,而只是分隔符或分组符(如果您愿意的话)。也许 #theme 回调仅适用于表单元素?

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?

别理我 2024-09-07 01:41:32

代码的概念有效,这意味着您可以做您想做的事情。

有一些事情可以解释为什么它不起作用。

  • 该字段集不是 $form['Basic Account Info']
  • 需要清除缓存。
  • $form['Basic Account Info']['#theme'] 在代码执行稍后会丢失/覆盖。

在进行任何审核之前,请尝试查看 $form。当我尝试复制您的代码时遇到一个错误:

  • 需要加载 user.pages.inc 文件

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
别念他 2024-09-07 01:41:32

我也有同样的问题。

您需要使用 #theme_wrappers 而不是 #theme

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

I was having the same issue.

You need to use #theme_wrappers instead of #theme

'#type' => 'fieldset',
'#theme_wrappers' => array('mymodule_fieldset'),
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文