Drupal7中自定义表格输入

Posted by Y Cheung on Sat, Jun 11, 2016

Drupal默认的节点表单(entity form)输入有时候并不能满足我们的需求,比如我想做一个类似excel表格输入形式的表单呢?

  • = DEMO点这里 (PS. 用Pantheon的sandbox做了一个随意折腾的drupal站点,真的是折腾死我了= =)

首先,新建一个自定义模块,在你的*.module文件中hook_menu() 指定一个页面路径,设置页面调用表单,比如这样:

 1function demo_tableform_menu(){
 2    $items = array();
 3    $items['demo/theme_table_into_form'] = array(
 4        'title callback' => '表格方式輸入表單',
 5        'page callback' => 'drupal_get_form',
 6        'page arguments' => array('classroomtable_form'),
 7        'access callback' => TRUE,
 8    );
 9
10    return $items;
11}

然后hook_form()把这个表格的基本元素写出来,用#header标签设置表格的表头部分,填充表格的每一行就用#rows标签,表单元素常见的input name用#name表示,标签#theme是用来设置之后如何渲染这个表单的,最后用$form['submit']设置表单提交后的动作。这整段的代码可以写成这样:

 1function classroomtable_form($form, &$form_state){
 2    $header = array(
 3        'sex'=>'性別',
 4        'number'=>'人數',
 5        'height'=>'平均身高',
 6        'classroom'=>'班級',
 7    );
 8    $options = array();
 9    $options[] = array(
10        'sex' =>array(
11            'data' =>array(
12                '#type'=>'select',
13                '#name'=>'sex',
14                '#options'=>array(
15                    'F'=>'女',
16                    'M'=>'男'
17                ),
18            ),
19        ),
20        'number'=>array(
21            'data'=>array(
22                '#type'=>'textfield',
23                '#name'=>'number',
24                '#attributes'=>array(
25                    'placeholder' => 0,
26                ),
27                '#size'=>12,
28            ),
29        ),
30        'height'=>array(
31            'data'=>array(
32                '#type'=>'textfield',
33                '#name' => 'height',
34                '#attributes' => array(
35                    'placeholder' => 0,
36                ),
37                '#size'=>12,
38            ),
39        ),
40        'classroom'=>array(
41            'data'=>array(
42                '#type'=>'textfield',
43                '#name' => 'classroom',
44                '#size' => 12,
45            ),
46        ),
47    );
48
49    $form['table'] = array(
50        '#theme' => 'demo_tableform_form',
51        '#header' => $header,
52        '#tree' => TRUE,
53        '#rows' => $options,
54        '#empty' => t('No content available.'),
55    );
56
57    $form['submit'] = array(
58        '#type' => 'submit',
59        '#submit' => array('classroomtable_submit'),
60        '#value' => t('Save'),
61    );
62
63    return $form;
64}

比较方便的是,利用rows array key的设置还能区分每一行的不同值,比如下面这段代码,表单提交后sex[3]就是用户在这行选择的值了,在多行表单中这种区分有时是非常有用的 :

 1 $key = 3;
 2 $options[$key] = array(
 3    'sex' =>array(
 4            'data' =>array(
 5                '#type'=>'select',
 6                '#name'=>'sex[{$key}]',
 7                '#options'=>array(
 8                    'F'=>'女',
 9                    'M'=>'男'
10                ),
11            ),
12        ),
13...

表格(table render)渲染部分:

 1/**
 2 * @return array
 3 */
 4function demo_tableform_theme()
 5{
 6    return array(
 7        'demo_tableform_form' => array(
 8            'render element' => 'form',
 9        ),
10    );
11}
12
13/**
14 * @param $variable
15 * @return string
16 */
17function theme_demo_tableform_form(&$variable)
18{
19    $form = $variable['form'];
20    $rows = $form['#rows'];
21    $header = $form['#header'];
22    $content = array(
23        '#theme' => 'table',
24        '#header' => $header,
25        '#rows' => $rows,
26    );
27    return drupal_render($content);
28}

最后把表单提交后的逻辑写一写就大功告成啦!表单提交内容用的是$form_state['input']内的值。

 1function classroomtable_submit($form, &$form_state){
 2    $sex = $form_state['input']['sex']; //F or M
 3    $number = $form_state['input']['number']; //int
 4    $height = $form_state['input']['height']; //demecal
 5    $classroom = $form_state['input']['classroom'];  //text
 6    if($number <= 0 || !(is_numeric($number) && is_int($number+0))){
 7        form_set_error('number','请输入正确的人数');
 8    }elseif($height <= 0|| !(is_numeric($height))){
 9        form_set_error('height','请输入正确的身高');
10    }else{
11        $entity = entity_create('class_resourece',array('type'=>'class_resourece_basic'));
12        $ew = entity_metadata_wrapper('class_resourece', $entity);
13        $ew->created->set(time());
14        $ew->field_gender->set($sex);
15        $ew->field_numberof->set($number);
16        $ew->field_heights->set($height);
17        $ew->field_class->set($classroom);
18        $ew->save();
19        $form_state['redirect'] = '<front>';
20    }
21}