快轉到主要內容

在DRUPAL 7自定義多行表格表單中設置添加行按鈕與刪除行按鈕

·1506 字·4 分鐘
Y Cheung
作者
Y Cheung
Blogger, Programer & Traveler.
目錄

標題有點拗口,YCHEUNG也想不出來更好的中文表達,沒懂的朋友直接看內文吧(或者看url的英文標題)。

這種功能的表格表單YCHEUNG已經嘗試了五六種方式來寫,但都不滿意。不然就是功能上多少有缺陷,比如無法使用drupal 7 form API的日期type,不然就是很繁瑣的一堆代碼和判斷,看着都頭暈……等,今天終於試出了一個令YCHEUNG較滿意的寫法!分享給大家,也是一種記錄,YCHEUNG有預感,之後還會寫很多個這樣的表單QAQ

最終效果
#

  • 效果圖一

頁面默認加載出來的表單只有一行,使用時如有需要則點擊繼續添加按鈕,操作一列因目前僅只有一行,不能作刪除操作,不顯示刪除按鈕。產品字段是自動補全的entity reference,三個時間字段是H:i格式用的是jQuery UI Timepicker

表格表單效果圖一
  • 效果圖二

點擊繼續添加按鈕後,表格表單增加一行,並且顯示刪除按鈕。

表格表單效果圖二

操作步驟
#

新建一個模組module(本文中模組命名為production,此步驟略)

production.module文件中HOOK_MENU()

 1/**
 2 * Implements hook_menu().
 3 */
 4function production_menu() {
 5  return array(
 6  'admin/production/add' = array(
 7    'title' => '添加表格表單',
 8    'access arguments' => array('access administration pages'),
 9    'type' => MENU_LOCAL_ACTION,
10    'page callback' => 'drupal_get_form',
11    'page arguments' => array('production_new_form'),
12    'file' => 'includes/production_admin.form.inc',
13  );
14);
15}

在文件production_admin.form.inc中先自定義一個標準的表單,$form_state['num']表示當前表格的總行數,然後循環打印出每一行,並且當行數不止一行的時候才現實刪除行按鈕。

 1function production_new_form($form, &$form_state) {
 2
 3  if (empty($form_state['num'])) {
 4    $form_state['num'] = 1;
 5  }
 6  $form = array(
 7    '#prefix' => '<div id="addtemplate-form-wrapper">',
 8    '#suffix' => '</div>',
 9  );
10  $form['data']['und']['#tree'] = TRUE; //很重要
11
12  for ($i = 0; $i < $form_state['num']; $i++) {
13    $form['data']['und'][$i] = array(
14      'productname' => array(
15        '#type' => 'textfield',
16        '#size' => 40,
17        '#autocomplete_path' => 'entityreference/autocomplete/single/field_productionitemname/field_collection_item/field_productionitem/NULL',
18      ),
19      'order_time' => array(
20        '#type' => 'textfield',
21        '#size' => 12,
22        '#attributes' => array(
23          'class' => ['form-text-sort', 'form-text-timefield'],
24        ),
25      ),
26      'start_time' => array(
27        '#type' => 'textfield',
28        '#size' => 12,
29        '#attributes' => array(
30          'class' => ['form-text-sort', 'form-text-timefield'],
31        ),
32      ),
33      'end_time' => array(
34        '#type' => 'textfield',
35        '#size' => 12,
36        '#attributes' => array(
37          'class' => ['form-text-sort', 'form-text-timefield'],
38        ),
39      ),
40    );
41    if ($form_state['num'] > 1) {
42      $form['data']['und'][$i]['remove_button'] = array(
43        'data' => array(
44          '#type' => 'submit',
45          '#value' => t('Remove'),
46          '#name' => 'remove-' . $i,
47          '#submit' => array('item_remove_one_submit'),
48          '#ajax' => array(
49            'callback' => 'item_add_and_remove_callback',
50            'wrapper' => 'addtemplate-form-wrapper',
51          ),
52          '#limit_validation_errors' => array(),
53        ),
54      );
55    }
56  }
57  $form['data']['actions']['add_more'] = array(
58    '#type' => 'submit',
59    '#value' => '继续添加',
60    '#limit_validation_errors' => array(),
61    '#submit' => array('item_add_more_submit'),
62    '#ajax' => array(
63      'callback' => 'item_add_and_remove_callback',
64      'wrapper' => 'addtemplate-form-wrapper',
65      'effect' => 'fade',
66    ),
67    '#weight' => 10,
68  );
69  $form['actions']['save'] = array(
70    '#type' => 'submit',
71    '#value' => '保存',
72    '#weight' => 11,
73  );
74  $form['#attached']['js'][] = libraries_get_path('jquery.timepicker') . '/include/ui-1.10.0/jquery.ui.core.min.js';
75  $form['#attached']['js'][] = libraries_get_path('jquery.timepicker') . '/include/ui-1.10.0/jquery.ui.position.min.js';
76  $form['#attached']['js'][] = libraries_get_path('jquery.timepicker') . '/jquery.ui.timepicker.js';
77  $form['#attached']['js'][] = drupal_get_path('module', 'production') . '/js/timefield.js';
78  $form['#attached']['css'][] = libraries_get_path('jquery.timepicker') . '/jquery.ui.timepicker.css';
79
80  return $form;
81}

將表單form轉成table的形式顯示。先hook_theme()theme_production_form()

 1/**
 2 * Implements hook_theme().
 3 */
 4function production_theme($existing, $type, $theme, $path) {
 5  return array(
 6    'production_new_form' => array(
 7      'render element' => 'form',
 8    ),
 9  );
10}
11
12function theme_production_new_form(&$vars) {
13  $form = $vars['form'];
14  $rows = array();
15  foreach (element_children($form['data']['und']) as $id) {
16    $rows[] = array(
17      'data' => array(
18        'productname' => drupal_render($form['data']['und'][$id]['productname']),
19        'order_time' => drupal_render($form['data']['und'][$id]['order_time']),
20        'start_time' => drupal_render($form['data']['und'][$id]['start_time']),
21        'end_time' => drupal_render($form['data']['und'][$id]['end_time']),
22        'remove_button' => drupal_render($form['data']['und'][$id]['remove_button']),
23      ),
24    );
25  }
26  $header = array(
27    'name' => '产品',
28    'order_time' => '开始生产时间',
29    'start_time' => '开始供应时间',
30    'end_time' => '结束供应时间',
31    'remove_button' => '操作',
32  );
33
34  $output = theme('table', array(
35    'header' => $header,
36    'rows' => $rows,
37    'tree' => TRUE,
38  ));
39  $output .= drupal_render_children($form);
40  return $output;
41}

添加和刪除按鈕是個ajax提交,重點就在這個submit和ajax callback function里!添加一行就是把 $form_state['num'] 增加一,反之就是減一。另一個關鍵是,要知道刪除的究竟是那一行的數據。所以 YCHEUNG 在刪除按鈕的name屬性上做文章,記錄當前的行順序ID,然後在提交中把這個這一行的填寫的數據unset刪除,並且把表格表單中填寫的數據結果集重新索引排序。最後重建表單。

 1function item_add_and_remove_callback($form, &$form_state) {
 2  return $form;
 3}
 4
 5function item_add_more_submit($form, &$form_state) {
 6  $form_state['num']++;
 7  $form_state['rebuild'] = TRUE;
 8}
 9
10function item_remove_one_submit($form, &$form_state) {
11  $button_name = explode('-', $form_state['triggering_element']['#name']);
12  if ($button_name[0] == 'remove') {
13    $row_id = $button_name[1];
14    unset($form_state['input']['und'][$row_id]);
15    $form_state['input']['und'] = array_values($form_state['input']['und']);
16  }
17  $form_state['num']--;
18  $form_state['rebuild'] = TRUE;
19}

這樣~就寫出了一個相對乾淨的表單啦,而且可以使用各種field type,是不是很贊呢XDDD

Reference
#

相關文章

drupal 7中操作遠程oracle數據庫

·584 字·2 分鐘
系統環境需求 # PHP環境最好是 PHP 7,系統最好是紅帽系。 操作步驟 # 安裝Oracle Instant Client # 在Oracle官網頁面中找到系統對應的客戶端下載安裝,比如Y CHEUNG選擇的就是 Instant Client Downloads for Linux x86-64 ,Fedora可以下載RPM包直接安裝,非RedHat系統的可能需要先編譯,用make install的方式安裝。

Drupal7中自定义表格输入

·1240 字·3 分鐘
Drupal默认的节点表单(entity form)输入有时候并不能满足我们的需求,比如我想做一个类似excel表格输入形式的表单呢? = DEMO点这里 (PS. 用Pantheon的sandbox做了一个随意折腾的drupal站点,真的是折腾死我了= =) 首先,新建一个自定义模块,在你的*.module文件中hook_menu() 指定一个页面路径,设置页面调用表单,比如这样:

Drupal7 中Restful模组应用简单介绍

·1918 字·4 分鐘
安装并启用Restful Module # Restful 2.x 下载 drush 安装 drush dl restful, drush en restful 自定义RESTFUL API模组 # 可参考restful里的范例 sites/all/modules/restful/modules/restful_example 或者测试文件内容 sites/all/modules/restful/tests 模组文件结构 # 1custom_restfulapi/ 2├─ src/ 3│ ├─ Plugin/ 4│ │ ├─ resource/ 5│ │ │ ├─ entity/ 6│ │ │ │ ├─ Testentity__1_0.php 7├─ custom_restfulapi.info 8├─ custom_restfulapi.module API RESOURCES要放在src/Plugin下。 *.info 和 *.module 的内容跟其他自定义模组的相差无几,方法一样,此处从略。

Centos 7 使用 certbot 安裝Let’s Encrypt SSL 證書

·707 字·2 分鐘
安裝環境 # CentOS7 主機 Nginx 操作步驟 # 安裝certbot # 1#如果你已經安裝了EPEL,這個步驟可以省略 2sudo yum install epel-release 3#安裝certbot客戶端 4sudo yum install certbot 使用嚮導自動安裝證書 # 使用certbot嚮導安裝,有界面,根據指示一步步操作就行,但是YCHEUNG進行到設置webroot的時候就error了,只好放棄