Chip Cullen - 星期四,04/04/2013 - 15:15
欢迎各位兄弟 发布技术文章
这里的技术是共享的
今天我花了很多时间试图找出我在Drupal网站上创建的形式的东西.我正在使用上一个和下一个按钮构建一个多步骤表单,这两个按钮都是这样的提交元素.
我需要做的是覆盖这些并使它们成为按钮元素而不是输入元素.这涉及在我的模板中创建一个看起来像这样的主题功能.您也可以使用hook_theme_registry_alter()添加主题覆盖,在模块中执行此操作.
/ **
*覆盖theme_button().
*
*将按钮元素渲染为按钮,并将submit元素作为输入元素.
* /
function mytheme_button ($ variables ) {
$ element = $ variables [ 'element' ] ;
$ element [ '#attributes' ] [ 'type' ] = 'submit' ;
element_set_attributes ($ element , array('id' , 'name' , 'value' ));
$ element [ '#attributes' ] [ 'class' ] [ ] = 'form-' . $ element [ '#button_type' ] ;
if (!empty($ element [ '#attributes' ] [ 'disabled' ] )) {
$ element [ '#attributes' ] [ 'class' ] [ ] = 'form-button-disabled' ;
}
if (isset($ element [ '#buttontype' ] ) && $ element [ '#buttontype' ] == 'button' ) {
$ value = $ element [ '#value' ] ;
unset($ element [ '#attributes' ] [ 'value' ] );
return '<button .=“”drupal_attributes =“”>' . $ value . '</ button>' ;
}
else {
return '<input .=“”drupal_attributes =“”/>' ;
}
}
然后我将上一个和下一个按钮定义更改为如下所示.元素仍然是提交表单元素,但它们通过使用#buttontype自定义属性呈现为按钮.
$ form [ 'prev' ] = array(
'#type' => '提交' ,
'#name' => '上一步' ,
'#validate' => array(
'mymodule_previous_validate'
),
'#submit' => array(
'mymodule_previous_submit'
),
'#buttontype' => '按钮' ,
'#value' => '<i class =“icon-chevron-left”> </ i>' .t ('上一步' ),
);
$ form [ 'next' ] = array(
'#type' => '提交' ,
'#name' => '下一步' ,
'#submit' => array(
'mymodule_next_submit'
),
'#buttontype' => '按钮' ,
'#value' => t ('下一步' ) . '<i class =“icon-chevron-right”> </ i>' ,
);
所有这些都在表单上生成了以下输出.
<button class =“form-submit”type =“submit”id =“edit-prev”name =“prev”> <i class =“icon-chevron-left”> </ i>上一步</ button>
<button class =“pull-right form-submit”type =“submit”id =“edit-next”name =“next”>下一步<i class =“icon-chevron-right”> </ i> </button>
这一切都适用于包含单个按钮元素的表单(如多步骤过程中的第一个表单),但如果表单上存在另一个按钮或提交元素,则全部失败.似乎在提交表单时,它既没有做任何事情,也没有返回页面.也没有正确的验证或提交功能,所以我不得不深入研究.
经过大量挖掘并跟随表单代码执行后,我设法弄清楚Drupal无法看到点击了什么按钮,因此假设表单中定义的第一个按钮是正确的元素.这与我在前一个按钮被执行时看到的行为相关,即使点击下一个按钮也是如此.该表单的某些页面上有“添加新项目”AJAX按钮,这些按钮首先由表单处理选取,这意味着没有正确的函数被处理.
导致此问题的代码位于form_builder()函数中.在表单处理验证和提交函数之前,$ form_state数组中的triggering_element项被强制为在表单上找到的第一个按钮(如果尚未设置).
function form_builder ($ form_id , &$ element , &$ form_state ) {
// ...剪断
if (isset($ element [ '#type' ] ) && $ element [ '#type' ] == 'form' ) {
// ...剪断
if (!$ form_state [ 'programmed' ] && !isset($ form_state [ 'triggering_element' ] ) && !empty($ form_state [ 'buttons' ] )) {
$ form_state [ 'triggering_element' ] = $ form_state [ 'buttons' ] [ 0 ] ;
}
//如果触发元素指定“按钮级”验证并提交
//运行处理程序而不是默认的表单级别,然后将其添加到
//表单状态
foreach (array('validate' , 'submit' ) as $ type ) {
if (isset($ form_state [ 'triggering_element' ] [ '#' . $ type ] )) {
$ form_state [ $ type . '_handlers' ] = $ form_state [ 'triggering_element' ] [ '#' . $ type ] ;
}
}
// ...剪断
}
// ...剪断
}
我发现我可以通过使用表单的#after_build属性以我想要的方式执行代码.这是在处理表单时运行的,并且允许我在$ form_state数组到达上面的代码之前添加正确的设置.
$form['#after_build'][] = 'mymodule_force_triggering_element';
#after_build元素中的函数用于确定单击了哪个按钮.$ form_state数组的input元素中存在正确的按钮,因此一个简单的逻辑允许我为表单状态添加正确的triggering_element.
function mymodule_force_triggering_element ($ form , &$ form_state ) {
if (isset($ form_state [ 'input' ] [ 'next' ] )) {
$ form_state [ 'triggering_element' ] = $ form [ 'next' ] ;
} elseif (isset($ form_state [ 'input' ] [ 'prev' ] )) {
$ form_state [ 'triggering_element' ] = $ form [ 'prev' ] ;
}
return $ form ;
}
在此之后,表单正常运行,正确的按钮运行正确的行为.我希望这有助于其他有同样问题的Drupal开发者.
Chip Cullen - 星期四,04/04/2013 - 15:15
philipnorton42 - 星期四,04/04/2013 - 15:24
迈克 - 星期二,2014年7月29日 - 01:56
迈克 - 星期二,2014年7月29日 - 02:11
$ form [ 'actions' ] [ 'submit' ] = array(
'#markup' => '<button type =“submit”.... =“”..... =“”> </ button>
吉姆 - 星期三,2015年7月15日 - 17:26
克里斯 - 星期二,10/20/2015 - 06:00
Rich - Fri,09/16/2016 - 10:23
然后在CSS中:
function my_form () {
$ form [ 'submit' ] = [ '#type' => 'submit' , '#value' => 'Go' ,
'#prefix' => '<span class =“icon”> </ span>' ,
'#ajax' => ......等等.
] ;
// ...
return $ form ;
}
这基本上只是在提交按钮的顶部粘贴一个图标.
span.icon {
background-image:url(path/to/icon);
position:absolute;
margin-left:1em;
margin-top:0.5em;
pointer-events:none;
}
input[type="submit"] {
border:solid 1px black;
padding:0.5em 1em 0.5em 3em;
}
pointer-events
是否有点击通过它到下面的按钮.这是一个黑客,但它是一个小黑客:-)