Drupal 6 Tabledrag 表单
Drupal6中的tabledrag表单是任何允许您在列表中上下移动项目或进入项目层次结构的表单。这实际上是Drupal本身的一个组件,用于菜单、分类和块管理等形式。Tabledrag是一种允许您的用户轻松地在列表中上下移动项目的好方法,他们将习惯网站其他区域的机制。
本质上,tabledrag是表单中的普通HTML表格,其中包含一些表单元素和一些JavaScript,这些JavaScript会将表格转换为一组可排序的元素。
我需要在最近的一个项目中创建一个tabledrag表单,但是在没有找到很多关于在线创建一个完整工作表单的好教程后,我决定写一个。这将带您了解使基于重量的tabledrag表单工作所需的基础知识,并且还将为您提供一个工作模块。
我们需要做的第一件事是为我们的tabledrag表单创建一个模块。创建一个名为mycustomtabledrag的模块文件夹并创建以下mycustomtabledrag.info文件。
name = Custom Table Drag description = Creates a tabledrag element version = 1.0 core = 6.x
接下来,创建一个名为的文件mycustomtabledrag.module并将其放置在mycustomtabledrag模块目录中。目前这将只包含以下文件存根,但我们稍后会为其添加功能。
为了使tabledrag表单正常工作,您需要有一个包含权重值的组件列表。这个权重值是一个整数值,当表单的元素移动时会更新,对于表单的正确工作是必不可少的。我认为最好创建由表单更新的真实数据,而不是乱七八糟的数组值。为此,我创建了一个数据库表,用于存储模块中使用的电子邮件和个人数据。
创建一个名为的文件mycustomtabledrag.install并将其与mycustomtabledrag.info文件一起放入模块目录中。Drupal在安装和卸载模块时使用.install文件。我不会在这里详细介绍(尤其是所有这些信息都可以在drupal.org上找到),但本质上发生的是Drupal将创建一个名为mycustomtabledrag_emaillink的表,其中将包含id、person、email和weight。
这是mycustomtabledrag.install文件的代码。如果您现在启用该模块,您会发现发生的事情并不多(还没有任何模块代码),但表已创建。
'People linked to email addresses.', 'fields' => array( 'id' => array( 'description' => 'The person and email ID', 'type' => 'serial', 'not null' => TRUE, ), 'person' => array( 'description' => 'The person', 'type' => 'varchar', 'length' => '255', 'not null' => TRUE, ), 'email' => array( 'description' => 'The email associated with this person', 'type' => 'varchar', 'length' => '255', 'not null' => TRUE, ), 'weight' => array( 'description' => 'The weight', 'type' => 'int', 'not null' => FALSE, ), ), 'primary key' => array('id'), 'indexes' => array( 'person' => array('person'), ), ); return $schema; }现在我们有一个数据资源可以使用(即mycustomtabledrag_emaillink表),我们现在可以充实模块的其余部分来创建tabledrag表单。
第一步是注册一个菜单回调函数来显示一个将显示表单的页面。这将创建一个页面,该页面将调用该drupal_get_form()函数并将该函数的返回值传递给它mycustomtabledrag_emaillink_form(),从而显示该表单。
/** * Implementation of hook_menu() */ function mycustomtabledrag_menu() { $items = array(); //添加回调页面显示表单 $items['mycustomtabledrag'] = array( 'title' => 'Custom Table Drag', 'page callback' => 'drupal_get_form', 'page arguments' => array('mycustomtabledrag_emaillink_form'), 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); return $items; }下一步是为tablesort元素的呈现注册一个主题函数。我们稍后会谈到主题函数,但是Drupal需要这个钩子来知道我们的模块中有哪些主题函数可用。我们传递给函数的唯一属性是表单。
/** * Implementation of hook_theme(). */ function mycustomtabledrag_theme() { return array( 'mycustomtabledrag_emaillink_form' => array( 'arguments' => array( 'form' => NULL ), ), ); }现在我们有了所有的钩子,我们可以定义表单创建函数。这将定义一个带有tablesort元素(以一组行元素的形式)的表单,一个包含将数据输入到表中并提交表单所需的字段的字段集。
要创建行,我们首先查询mycustomtabledrag_emaillink表中的所有数据(按重量排序),并将其作为一组行元素插入到表单中。然后数组中的每个项目都包含每个数据项作为表单元素。如果我们使用当前插入的代码运行模块,那么我们将看到一个表单元素列表,但没有tabledrag元素。将这个行数组转换为表格并添加tabledrag功能的是主题函数。
函数代码中需要注意的一件重要事情是向权重元素添加了一个类。tablesortJavaScript代码使用它来隐藏权重元素,并在元素顺序改变时更新它们。
/** * Implementation of hook_form(). */ function mycustomtabledrag_emaillink_form(&$form_state) { $form = array(); $form['#method'] = 'post'; //获取tablesort元素的数据 $result = db_query("SELECT id, person, email, weight FROM {mycustomtabledrag_emaillink} ORDER BY weight ASC"); while ($row = db_fetch_object($result)) { $form['rows'][$row->id]['person_' . $row->id] = array( '#type' => 'textfield', '#size' => 35, '#default_value' => $row->person, ); $form['rows'][$row->id]['email_' . $row->id] = array( '#type' => 'textfield', '#size' => 35, '#default_value' => $row->email, ); //现在创建权重表单元素。 $form['rows'][$row->id]['weight_' . $row->id] = array( '#type' => 'weight', '#size' => 5, '#delta' => 50, '#default_value' => $row->weight, //在这里添加一个特定的类-我们稍后需要这个 '#attributes' => array('class' => 'weight'), ); } $form['person_fieldset'] = array( '#type' => 'fieldset', '#title' => t('New Person And Email Combination'), '#collapsible' => TRUE, '#collapsed' => TRUE ); $form['person_fieldset']['person_0'] = array( '#type' => 'textfield', '#title' => t('Person'), ); $form['person_fieldset']['email_0'] = array( '#type' => 'textfield', '#title' => t('Email'), ); //不要忘记提交按钮 $form['submit'] = array( '#type' => 'submit', '#value' => t('Save changes'), ); return $form; }有了所有这些,我们现在可以开始将主题应用于tabledrag表单。mycustomtabledrag_theme()上面的函数详细介绍了一个名为theme_mycustomtabledrag_emaillink_form().这里要意识到的重要一点是,因为我们已经调用了表单定义函数mycustomtabledrag_emaillink_form(),所以我们定义的任何名为“theme_[formname]”的主题函数都将被Drupal选取并用于对表单进行主题化。这很重要,因为您在复制代码时可能会更改函数名称,因此您必须考虑到这一点。
这个函数的作用是遍历我们在表单中定义的每个“行”并呈现它包含的表单元素。完成后,我们将元素呈现为表格,然后将结果作为HTML表单元素存储回行数组。表单渲染完成后,我们运行一个函数drupal_add_tabledrag(),让Drupal知道我们的表单包含一个tabledrag组件。该drupal_add_tabledrag()函数会将所需的JavaScript元素添加到页面,以便tabledrag元素可以工作。
/** * Theme function for the mycustomtabledrag_emaillink_form form. */ function theme_mycustomtabledrag_emaillink_form($form) { $table_rows = array(); if (is_array($form['rows'])) { foreach ($form['rows'] as $id => $row) { //我们只对数字键感兴趣 if (intval($id)) { $this_row = array(); $this_row[] = drupal_render($form['rows'][$id]['person_' . $id]); $this_row[] = drupal_render($form['rows'][$id]['email_' . $id]); //将权重字段添加到行 $this_row[] = drupal_render($form['rows'][$id]['weight_' . $id]); //将行添加到行数组 $table_rows[] = array('data' => $this_row, 'class' => 'draggable'); } } } //设置表格标题。 $header = array( "Person", "Email", "Weight" ); //将表单元素渲染到表格中。 $form['rows'] = array( '#value' => theme('table', $header, $table_rows, array('id' => 'person-email')) ); //渲染整个表单 $output = drupal_render($form); //调用drupal_add_tabledrag添加和设置JavaScript。 //第一个参数是表ID,这对于找到正确的表至关重要。 //第四个参数是持有权重的表单项的类 drupal_add_tabledrag('person-email', 'order', 'sibling', 'weight'); return $output; }上面的代码包含tabledrag表单的最简单版本,其中元素仅上下移动。该drupal_add_tabledrag()函数采用许多参数,值得单独处理,因为它们可以改变表单的行为。
从上面的属性可以看出,可以在不同元素之间建立层次结构,但是我们在mycustomtabledrag模块中设置的变量只允许设置基于权重的排序。要创建选项层次结构,您需要创建一个变量来存储不同元素之间的关系以及存储它的方法。如果您想创建一个具有层次结构的模块,那么您需要在模块设计的早期做出决定,以便您可以将其纳入您的代码。
这个模块的最后一部分是向我们的表单添加提交和验证功能,以便我们可以在保存之前确保数据的有效性。您可以将它们硬编码到表单定义中,也可以将它们编写为hook_form_submit()和hook_form_validate()函数。以下代码包含对电子邮件地址的一些简单验证,并允许保存和更新表单中的数据。
/** * Implementation of hook_form_validate(). */ function mycustomtabledrag_emaillink_form_validate($form, &$form_state) { foreach ($form_state['values'] as $key => $value) { if (($key == 'email_0' && trim($value) != '') || ($key != 'email_0' && strpos($key, 'email_') !== FALSE)) { if (valid_email_address($form_state['values'][$key]) == FALSE) { form_set_error($key, t('Please enter a valid email address')); } } } } /** * Implementation of hook_form_submit(). */ function mycustomtabledrag_emaillink_form_submit($form, &$form_state) { $emaillink = array(); foreach ($form_state['values'] as $key => $value) { if (strpos($key, 'person_') !== FALSE || strpos($key, 'email_') !== FALSE || strpos($key, 'weight_') !== FALSE) { $replace_elements = array('person_', 'email_', 'id_', 'weight_'); //从元素数据中提取id和字段 $emaillink[str_replace($replace_elements, '', $key)][substr($key, 0, strpos($key, '_'))] = $value; } } //保存我们从表单值中恢复的项目。 foreach ($emaillink as $id => $email) { if ($id == 0 && $email['person'] != '' && $email['email'] != '') { db_query("INSERT INTO {mycustomtabledrag_emaillink}(person, email, weight) VALUES ('%s', '%s', 0)", $email['person'], $email['email']); } elseif ($email['person'] != '' && $email['email'] != '') { db_query("UPDATE {mycustomtabledrag_emaillink} SET person = '%s', email = '%s', weight = %d WHERE id = %d LIMIT 1", $email['person'], $email['email'], $email['weight'], $id); } } drupal_set_message('The email form has been updated.'); }从表中删除项目怎么样?这可以通过多种方式完成,但最好的方式可能是在表格上提供一个链接,该链接将删除相关项目。由于这并不是tabledrag功能的真正组成部分,因此我将其作为读者的任务而忽略了。
以下是该drupal_add_tabledrag()方法的完整参数 。
$table_id-这是一个包含我们想要用作tabledrag表的表的ID的字符串。在我们的项目中,这个表ID是“person-email”,它是在我们将行呈现到表中时设置的。
$action-这是一个字符串,描述要为表单项执行的操作,可以是“匹配”、“深度”或“顺序”。Order(在本模块中使用)用于为具有相同组的其他表单元素设置权重。匹配用于父关系,深度更新使用当前缩进的目标元素。
$relationship-描述$action变量应该在哪里执行的字符串,可以是“parent”、“sibling”、“group”或“self”。
父级将影响树上的元素。
同级将在与其上方和下方的行相同的组中查找字段。这在上面的模块代码中使用,因为我们只需要更改几个元素的权重。
Self影响拖动的行本身。
组会影响拖动的行及其下方的任何子项。这意味着如果拖动一个组,那么它下面的所有内容也将随之携带。
$group-这是用于将所有相关项目组合在一起的类名。在我们在这里创建的示例模块中,我们用来将事物组合在一起的类是“权重”,它包含一个表单元素,该元素在表更改时更新。
$subgroup-(可选)这是一个字符串,用于定义用于创建层次结构的字段。这与$group参数的使用方式大致相同,但仅在设置具有层次结构的表时使用。这个参数的用法可以通过$action参数的值来改变。
$source-(可选)如果$action是“匹配”,则此字符串应包含类名,用于标识在匹配$subgroup中的值时将用作源值的字段。
$hidden-(可选)这是一个字符串,可用于在视图中隐藏列。此处的默认行为是隐藏权重和父表单元素,但也可以将其设置为FALSE以停止隐藏任何内容。
$limit-(可选)这是一个整数,表示层次结构可以具有的最大级别数。出于此模块的目的,我们尚未设置此项,因此该值将为0。