欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

在Drupal 7中将提交输入元素更改为按钮

今天我花了很多时间试图找出我在Drupal网站上创建的形式的东西.我正在使用上一个和下一个按钮构建一个多步骤表单,这两个按钮都是这样的提交元素.

  1. $ form [ 'next' ] = array(

  2. '#type' => '提交'

  3. '#name' => '下一步'

  4. '#submit' => array(

  5. 'mymodule_next_submit'

  6. )

  7. '#value' => '下一步'

  8. );


我需要做的是覆盖这些并使它们成为按钮元素而不是输入元素.这涉及在我的模板中创建一个看起来像这样的主题功能.您也可以使用hook_theme_registry_alter()添加主题覆盖,在模块中执行此操作.

  1. / **

  2.  *覆盖theme_button().

  3.  *

  4.  *将按钮元素渲染为按钮,并将submit元素作为输入元素.

  5.  * /

  6. function mytheme_button ($ variables ) {

  7. $ element = $ variables [ 'element' ] ;

  8. $ element [ '#attributes' ] [ 'type' ] = 'submit' ;

  9.  

  10.  element_set_attributes ($ element array('id' 'name' 'value' ));

  11.  

  12. $ element [ '#attributes' ] [ 'class' ] [ ] = 'form-' . $ element [ '#button_type' ] ;

  13. if (empty($ element [ '#attributes' ] [ 'disabled' ] )) {

  14. $ element [ '#attributes' ] [ 'class' ] [ ] = 'form-button-disabled' ;

  15. }

  16.  

  17. if (isset($ element [ '#buttontype' ] ) && $ element [ '#buttontype' ] == 'button' ) {

  18. $ value = $ element [ '#value' ] ;

  19. unset($ element [ '#attributes' ] [ 'value' ] );

  20. return '<button .=“”drupal_attributes =“”>' . $ value . '</ button>' ;

  21. }

  22. else {

  23. return '<input .=“”drupal_attributes =“”/>' ;

  24. }

  25. }


然后我将上一个和下一个按钮定义更改为如下所示.元素仍然是提交表单元素,但它们通过使用#buttontype自定义属性呈现为按钮.

  1. $ form [ 'prev' ] = array(

  2. '#type' => '提交'

  3. '#name' => '上一步'

  4. '#validate' => array(

  5. 'mymodule_previous_validate'

  6. )

  7. '#submit' => array(

  8. 'mymodule_previous_submit'

  9. )

  10. '#buttontype' => '按钮'

  11. '#value' => '<i class =“icon-chevron-left”> </ i>' .t ('上一步' )

  12. );

  13.  

  14. $ form [ 'next' ] = array(

  15. '#type' => '提交'

  16. '#name' => '下一步'

  17. '#submit' => array(

  18. 'mymodule_next_submit'

  19. )

  20. '#buttontype' => '按钮'

  21. '#value' => t ('下一步' ) . '<i class =“icon-chevron-right”> </ i>'

  22. );


所有这些都在表单上生成了以下输出.

  1. <button class =“form-submit”type =“submit”id =“edit-prev”name =“prev”> <i class =“icon-chevron-left”> </ i>上一步</ button>

  2. <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项被强制为在表单上找到的第一个按钮(如果尚未设置).

  1. function form_builder ($ form_id $ element $ form_state ) {

  2.  

  3. // ...剪断

  4.  

  5. if (isset($ element [ '#type' ] ) && $ element [ '#type' ] == 'form' ) {

  6.  

  7. // ...剪断

  8.  

  9. if ($ form_state [ 'programmed' ] && isset($ form_state [ 'triggering_element' ] ) && empty($ form_state [ 'buttons' ] )) {

  10. $ form_state [ 'triggering_element' ] = $ form_state [ 'buttons' ] [ 0 ] ;

  11. }

  12.  

  13. //如果触发元素指定“按钮级”验证并提交

  14. //运行处理程序而不是默认的表单级别,然后将其添加到

  15. //表单状态

  16. foreach (array('validate' 'submit' ) as $ type ) {

  17. if (isset($ form_state [ 'triggering_element' ] [ '#' . $ type ] )) {

  18. $ form_state [ $ type . '_handlers' ] = $ form_state [ 'triggering_element' ] [ '#' . $ type ] ;

  19. }

  20. }

  21.  

  22. // ...剪断

  23.  

  24. }

  25.  

  26. // ...剪断

  27. }


我发现我可以通过使用表单的#after_build属性以我想要的方式执行代码.这是在处理表单时运行的,并且允许我在$ form_state数组到达上面的代码之前添加正确的设置.

$form['#after_build'][] = 'mymodule_force_triggering_element';

#after_build元素中的函数用于确定单击了哪个按钮.$ form_state数组的input元素中存在正确的按钮,因此一个简单的逻辑允许我为表单状态添加正确的triggering_element.

  1. function mymodule_force_triggering_element ($ form $ form_state ) {

  2. if (isset($ form_state [ 'input' ] [ 'next' ] )) {

  3. $ form_state [ 'triggering_element' ] = $ form [ 'next' ] ;

  4. } elseif (isset($ form_state [ 'input' ] [ 'prev' ] )) {

  5. $ form_state [ 'triggering_element' ] = $ form [ 'prev' ] ;

  6. }

  7. return $ form ;

  8. }


在此之后,表单正常运行,正确的按钮运行正确的行为.我希望这有助于其他有同样问题的Drupal开发者.

类别Drupal的标签Drupal的

评论    

   
永久链接        

Chip Cullen - 星期四,04/04/2013 - 15:15            

只是想说谢谢你.我正在努力解决这个问题(为了使用图标,就像你一样),但是对于搜索框提交按钮.你的代码很棒 - 谢谢!    
   
永久链接        

philipnorton42 - 星期四,04/04/2013 - 15:24            

很高兴它很有帮助!我用它完全相同的东西:)    
   
永久链接        

迈克 - 星期二,2014年7月29日 - 01:56            

我也试图改变搜索框,但这显然做得更多.我怎样才能将其缩小到搜索框?    
   
永久链接        

迈克 - 星期二,2014年7月29日 - 02:11            

我成功地改变了输入元素......                
  1. $ form [ 'actions' ] [ 'submit' ] = array(

  2. '#markup' => '<button type =“submit”.... =“”..... =“”> </ button>

   
   
永久链接        

吉姆 - 星期三,2015年7月15日 - 17:26            

你在跟我开玩笑吗?!我一直在努力解决这个问题并围绕这个Drupal 7提交按钮“功能”进行设计.现在,我可以使用我想要的多个提交按钮来控制表单.谢谢!!!互联网FTW.    
   
永久链接        

克里斯 - 星期二,10/20/2015 - 06:00            

感谢您发布此内容.我继承的形式还有其他许多问题,但是这篇文章有助于阐明实际发生的事情并使其理顺.我只希望我早几个小时见过它.:)    
   
永久链接        

Rich - Fri,09/16/2016 - 10:23            

谢谢你,非常有用.最后,我采用了不同的解决方案:                
  1. function my_form () {

  2. $ form [ 'submit' ] = [ '#type' => 'submit' '#value' => 'Go'

  3. '#prefix' => '<span class =“icon”> </ span>'

  4. '#ajax' => ......等等.

  5. ] ;

  6. // ...

  7. return $ form ;

  8. }

然后在CSS中:                



  1. span.icon {



  2. background-image:url(path/to/icon);



  3. position:absolute;



  4. margin-left:1em;



  5. margin-top:0.5em;



  6. pointer-events:none;



  7. }



  8. input[type="submit"] {



  9. border:solid 1px black;



  10. padding:0.5em 1em 0.5em 3em;



  11. }

这基本上只是在提交按钮的顶部粘贴一个图标.pointer-events是否有点击通过它到下面的按钮.这是一个黑客,但它是一个小黑客:-)    

   



普通分类: