My main question is:
Does the theme_hook() function gets called whenever the form gets rebuilt via ahah (ahah_helper) ?
I'm trying to show a select box, with some filtering options, when the user changes it, the table below it changes too.
I have this by now:
function veiculos_listar_form($form_state)
{
$form = array();
ahah_helper_register($form, $form_state);
//biulds $options
$form['listar_veics'] = array(
'#type' => 'fieldset',
'#prefix' => '<div id="listar-veics-wrapper">',
'#suffix' => '</div>',
'#tree' => TRUE,
);
if (!isset($form_state['values']['listar_veics']['filial']))
$form['#filial_veic'] = 1;
else
$form['#filial_veic'] = $form_state['values']['listar_veics']['filial'];
$form['listar_veics']['filial'] = array(
'#type' => 'select',
'#title' => "Listar veículos da filial",
'#options' => $filiais,
'#default_value' => $form['#filial_veic'],
'#ahah' => array(
'event' => 'change',
'path' => ahah_helper_path(array('listar_veics')),
'wrapper' => 'listar-veics-wrapper',
'method' => 'replace',
),
);
return $form;
}
function veiculos_listar_form_submit($form, &$form_state)
{
}
function _listar_veiculos_tabela($filial)
{
//builds $header and $data
$table = theme_table($header, $data);
return $table;
}
function theme_veiculos_listar_form($form)
{
$output = drupal_render($form);
$filial = $form['#filial_veic'];
$output .= '<br>' . $filial . '<br>';
$output .= _listar_veiculos_tabela($filial);
return $output;
}
function veiculos_theme() {
return array(
'veiculos_listar_form' => array(
'arguments' => array('form' => NULL),),
);
}
In my little and innocent world, it should work if theme_hook is called on every ahah event (change).
The problem is, the variable printed is always the same, like what the user is choosing isn't being stored. If the user select a different options, it shows the new option, but the $filial variable is always the same when the theme prints.
Like this:
http://img230.imageshack.us/img230/9646/62144334.jpg
Any suggestion on what i could do to make this work? I'm developing our own module, so using views module isn't a good idea.
Thanks.
You should redo code this way.
Ahah callback I do not wrote, I think you would not have problem with it.
Check some examples on drupal.org
function veiculos_listar_form($form_state)
{
$form = array();
ahah_helper_register($form, $form_state);
//biulds $options
// remove divs because we do not want to reload selector with ahah
$form['listar_veics'] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
);
if (!isset($form_state['values']['listar_veics']['filial']))
$form['#filial_veic'] = 1;
else
$form['#filial_veic'] = $form_state['values']['listar_veics']['filial'];
// add cover div here, because we will reload table
$form['table'] = array(
'#prefix' => '<div id="listar-veics-wrapper">',
'#suffix' => '</div>',
'#type' => 'markup',
'#value' => _listar_veiculos_tabela($form['#filial_veic']),
);
$form['listar_veics']['filial'] = array(
'#type' => 'select',
'#title' => "Listar veículos da filial",
'#options' => $filiais,
'#default_value' => $form['#filial_veic'],
'#ahah' => array(
'event' => 'change',
'path' => ahah_helper_path(array('listar_veics')),
'wrapper' => 'listar-veics-wrapper',
'method' => 'replace',
),
);
return $form;
}
function veiculos_listar_form_submit($form, &$form_state)
{
}
function _listar_veiculos_tabela($filial)
{
//builds $header and $data
$table = theme_table($header, $data);
return $table;
}
function theme_veiculos_listar_form($form)
{
$output = drupal_render($form);
return $output;
}
function veiculos_theme() {
return array(
'veiculos_listar_form' => array(
'arguments' => array('form' => NULL),),
);
}
Related
I'm trying to use ajax in drupal 8 custom form. But it not work.
I've custom form, in which textfield is display with some value once the user click on the checkbox. Here is my code:-
public function buildForm(array $form, FormStateInterface $form_state) {
$form['del_name'] = array(
'#type' => 'checkbox',
'#title' => $this->t('Delete users, by name'),
'#ajax' => array(
'callback' => array($this, 'my_user_callback'),
'wrapper' => 'del-name',
),
);
$form['name_placeholder'] = array(
'#type' => 'hidden',
'#prefix' => '<div id="del-name">',
'#suffix' => '</div>',
'#tree' => TRUE,
);
if (!empty($form_state->getValue('del_name')) && $form_state->getValue('del_name')) {
/*
* $process_data = some stuff
*/
$form['name_placeholder']['user_role'] = array(
'#title' => $this->t('Users role'),
'#type' => 'textfield',
'#default_value' => $process_data
);
}
}
function my_user_callback(array &$form, FormStateInterface $form_state) {
return array(
'#type' => 'ajax',
'#commands' => array(
ajax_command_replace('#del-name', render($form['name_placeholder'])),
)
);
}
Problem is that, textfield not appear when checkbox is checked.
try this:
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
function my_user_callback(array &$form, FormStateInterface $form_state {
$response = new AjaxResponse();
$response->addCommand(new HtmlCommand(
'#wrapper-element-id',
$array_of_form_elements
));
return $response;
);
I am actually trying to build up a draggable table, but for some reason after implementing the theme_function, my submit handler is no longer getting called.
This is what my Code actually looks like:
function he_ministerienschalter_theme($existing, $type, $theme, $path) {
$themes = array(
'he_ministerienschalter_admin_form' => array(
'render element' => 'element',
),
);
return $themes;
}
/**
* Implements the ministerschalter admin form
*/
function he_ministerienschalter_admin_form($form, &$form_state, $form_id, $item) {
$domainnames = he_ministerienschalter_domainselect();
$count = 0;
$form['ressortswitch'] = array(
'#prefix' => '<div id="curve-attributes">',
'#suffix' => '</div>',
'#tree' => TRUE,
'#theme' => 'he_ministerienschalter_admin_form',
);
foreach ($domainnames as $key => $domainname) {
$form['ressortswitch'][$key]['domainID-'.$key] = array(
'#type' => 'value',
'#value' => $domainname['domain_id'],
);
$form['ressortswitch'][$key]['domainname-'.$key] = array(
'#type' => 'item',
'#title' => $domainname['sitename'],
'#size' => 60,
'#maxlength' => 128,
);
$form['ressortswitch'][$key]['domainshort-'.$key] = array(
'#type' => 'textfield',
'#default_value' => $domainname['sitename'],
);
$form['ressortswitch'][$key]['weight-'.$key] = array(
'#type' => 'textfield',
'#default_value' => !empty($domainname['domain_weight']) ? $domainname['domain_weight'] : '0',
'#size' => 3,
'#attributes' => array('class' => array('item-row-weight')),
);
$count++;
}
$form['ressortswitch']['count'] = array(
'#type' => 'hidden',
'#value' => $count,
);
$form['ressortswitch']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save Settings'),
);
return $form;
}
/**
* Theme callback for the he_ministerienschalter_admin_form
*/
function theme_he_ministerienschalter_admin_form($variables) {
$element = $variables['form'];
drupal_add_tabledrag('ressortswitch_table', 'order', 'sibling', 'item-row-weight');
$header = array(
t('Domainname'),
t('Domainshort'),
t('Weight')
);
$element_items = array();
foreach($element['ressortswitch'] as $id => $record) {
if(is_int($id)) {
$element_items[] = $record;
}
}
$rows = array();
foreach ($element_items as $id => $item) {
$domainNAME[$id] = $item['domainname-'.$id];
$domainSHORT[$id] = $item['domainshort-'.$id];
$domainWEIGHT[$id] = $item['weight-'.$id];
$rows[] = array(
'data' => array(
drupal_render($domainNAME[$id]),
drupal_render($domainSHORT[$id]),
drupal_render($domainWEIGHT[$id]),
),
'class' => array('draggable'),
);
}
$output = theme('table', array(
'header' => $header,
'rows' => $rows,
'attributes' => array('id' => 'ressortswitch_table'),
));
$output .= drupal_render($element['ressortswitch']['submit']);
return $output;
}
/**
* Implements hook_form_submit
*/
function he_ministerienschalter_admin_form_submit($form, &$form_state, $item) {
db_delete('he_ministerienschalter')
->execute();
$count_domains = $form_state['values']['ressortswitch']['count'];
$count = 0;
// dpm($form_state);
dpm($form_state);
while($count < $count_domains) {
db_insert('he_ministerienschalter')
->fields(array(
'domain_id' => $form_state['values']['ressortswitch'][$count]['domainID-'.$count],
'domain_short' => $form_state['values']['ressortswitch'][$count]['domainshort-'.$count],
'domain_weight' => $form_state['values']['ressortswitch'][$count]['weight-'.$count]
))
->execute();
$count++;
}
drupal_set_message('Eingabe gespeichert');
}
Any idea how to solve that?
I Updated my theme function like this and now it works like a charm :-)
$output .= drupal_render($element['form_id']);
$output .= drupal_render($element['form_build_id']);
$output .= drupal_render($element['form_token']);
I want to be able to select items from two select lists and then submit (which will take me to another form.
The following is the code I have however the submit function (submit_function) does not appear to get triggered (it just refreshes the form). What am I doing wrong?
function myfunction($form, &$form_state)
{
$output = drupal_render($element['form_id']);
$output .= drupal_render($element['form_build_id']);
$output .= drupal_render($element['form_token']);
$header = array(
'columnone' => t('Column 1'),
'columntwo' => t('Column 2'),
'columnthree' => t('Column 3'),
);
$rows = array(
array(
'columnone' => array(
'data' => array(
'#type' => 'select',
'#options' => columnoneoptions(),
),
),
'columntwo' => array(
'data' => array(
'#type' => 'select',
'#options' => columntwooptions(),
),
),
'columnthree' =>array(
'data' => array(
'#type' => 'submit',
'#value' => t('Add'),
'#weight' => 45,
'#submit' => array('submit_function'),
)
),
),
);
$output['table'] = array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#weight' => 2,
);
return $output;
}
That is quite normal, you are mixing form elements with static renderable elements. A drupal_get_form function expects a form build.
What you need to create is your custom form theme table which outputs a theme within a form build. Here is some sample code that could help you further:
function YOURMODULE_theme()
{
// define a table form theme
return array(
'YOURMODULE_table_form' => array(
'render element' => 'element'
),
);
}
function theme_YOURMODULE_table_form($vars)
{
$element = $vars['element'];
$form_keys = false;
$rows = array();
// loop through each row form elements
foreach (element_children($element) as $key) {
if (!$form_keys) {
$form_keys = array();
// retrieve the form keys for each row
foreach (element_children($element[$key]) as $f_key) {
$form_keys[$f_key] = isset($element[$key][$f_key]['#title'])
? $element[$key][$f_key]['#title']
: '';
}
}
$row = array();
foreach ($form_keys as $fieldkey => $fieldname) {
// render each field in a separate row
$row[] = array(
'data' => drupal_render($element[$key][$fieldkey])
);
}
$rows[] = $row;
}
// return a build for the table
return theme('table', array(
'header' => $vars['element']['#header'],
'rows' => $rows,
'empty' => isset($vars['element']['#empty'])
? $vars['element']['#header']
: '',
));
}
And the form using your logic:
function myfunction($form, &$form_state)
{
$form['table'] = array(
'#theme' => 'YOURMODULE_table_form',
'#header' => array(
'columnone' => t('Column 1'),
'columntwo' => t('Column 2'),
'columnthree' => t('Column 3'),
),
'#tree' => true,
);
$form['table'][0] = array(
'columnone' => array(
'#type' => 'select',
'#options' => columnoneoptions(),
),
'columntwo' => array(
'#type' => 'select',
'#options' => columntwooptions(),
),
'columnthree' => array(
'#type' => 'submit',
'#value' => t('Add'),
'#weight' => 45,
'#submit' => array('submit_function'),
),
);
return $form;
}
I'm quite new to Drupal and I want to create a custom grid that has some editable columns, some other columns witch checkboxes etc.
I'm using the theme() function to create the table and render it at the settings. Since I cannot find any way to access the form/settings variables, inside the theme function, I create a custom table at the drupal database that will contain the gid values, and I render those rows. For testing purposes I fetch the 'variables' table rows. Here is the code so far:
$form['module_settings']['profile_grid'] = array(
'#type' => 'item',
'#title' => t('Profile Mapping'),
'#theme' => 'profile_mapping_grid'
);
function theme_profile_mapping_grid($sender) {
$header = array('', t('name'), t('value'));
$result = db_query('SELECT v.name, v.value from {variable} v');
while ($pair = db_fetch_object($result)) {
$format = array(
'#type' => 'textfield',
'#size' => 30,
'#value' => $pair->name
);
$hhfield = array(
'#type' => 'textfield',
'#size' => 30,
'#value' => $pair->value
);
$row = array('');
$row[] = drupal_render($format);
$row[] = drupal_render($hhfield);
$rows[] = array('data' => $row);
}
$output = theme('table', $header, $rows, array('id' => 'gridErrors'));
return $output;
}
The grid is generated correctly, but I have an issue. I cannot set the 'name' attribute to the textfield, in order to collect it's value later on, on a submit action.
Furthermore, I'm not sure if this is the best way to create a settings grid.
Any ideas, opinions etc are more than welcome.
According to Drupal 6 Form API Quickstart Guide:
Don't use the '#value' attribute for any form element that can be changed by the user. Use the '#default_value' attribute instead. Don't put values from $form_state['values'] (or $_POST) here! FormsAPI will deal with that for you; only put the original value of the field here.
You have to use '#default_value' => $pair->name not '#value' => $pair->value.
Here is the sample module with settings table.
install file:
<?php
// $Id$
/**
* #file
* The your_module module install file, which handles the install/uninstall tasks.
*
*/
function your_module_install() {
// Create tables.
drupal_install_schema('your_module');
}
/**
* Implementation of hook_schema().
*/
function your_module_schema() {
/* Settings table */
$schema['your_module_settings'] = array(
'description' => 'Stores module settings.',
'fields' => array(
'record_id' => array(
'description' => 'The primary identifier for a record.',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE),
'item_code' => array(
'type' => 'varchar',
'length' => '255',
'not null' => TRUE),
'setting_one' => array(
'type' => 'varchar',
'length' => '255',
'not null' => TRUE),
'setting_two' => array(
'type' => 'varchar',
'length' => '255')),
'unique keys' => array(
'record_id' => array('record_id')),
'primary key' => array('record_id')
);
return $schema;
}
/**
* Implementation of hook_uninstall().
*/
function your_module_uninstall() {
// Remove tables.
drupal_uninstall_schema('your_module');
}
module file:
<?php
/**
* Implementation of hook_help()
*/
function your_module_help($path, $arg)
{
switch ($path)
{
case 'admin/help#your_module':
return '<p>'. t('Module description.') .'</p>';
}
}
/**
* Implementation of hook_menu()
*/
function your_module_menu()
{
$items = array();
/* module settings page */
$items['admin/settings/your_module'] = array(
'description' => 'Administer your_module module settings.',
'title' => 'Some title',
'page callback' => 'drupal_get_form',
'page arguments' => array('your_module_admin_settings'),
'access arguments' => array('access administration pages'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/**
* Implementation of hook_theme().
*/
function your_module_theme() {
return array(
'your_module_products_settings' => array(
'arguments' => array('form' => NULL),
),
);
}
/**
* Settings form
*/
function your_module_admin_settings(&$form_state)
{
$form['your_module'] = array(
'#type' => 'fieldset',
'#title' => t('Settings'),
'#description' => t('Settings description.'),
);
$form['your_module']['products_settings_table'] = array(
'#theme' => 'your_module_products_settings',
'#tree' => TRUE,
);
$form['your_module']['products_settings_table']['products_settings'] = array();
$result = db_query('SELECT record_id, item_code, setting_one, setting_two FROM {your_module_settings} ORDER BY item_code');
while ($product_setting = db_fetch_object($result)) {
$form['your_module']['products_settings_table']['products_settings'][$product_setting->record_id] = array();
$form['your_module']['products_settings_table']['products_settings'][$product_setting->record_id]['item_code'] = array(
'#type' => 'textfield',
'#default_value' => $product_setting->item_code,
'#size' => 8,
'#maxlength' => 16,
);
$form['your_module']['products_settings_table']['products_settings'][$product_setting->record_id]['setting_one'] = array(
'#type' => 'textfield',
'#default_value' => $product_setting->setting_one,
'#size' => 16,
'#maxlength' => 16,
);
$form['your_module']['products_settings_table']['products_settings'][$product_setting->record_id]['setting_two'] = array(
'#type' => 'textfield',
'#default_value' => $product_setting->setting_two,
'#size' => 40,
'#maxlength' => 255,
);
}
/* "add new row" fields */
$form['your_module']['products_settings_table']['products_settings_new'] = array();
/* new item_code */
$form['your_module']['products_settings_table']['products_settings_new']['item_code'] = array(
'#type' => 'textfield',
'#size' => 8,
'#maxlength' => 16,
'#description' => t('description'),
);
/* new setting_one */
$form['your_module']['products_settings_table']['products_settings_new']['setting_one'] = array(
'#type' => 'textfield',
'#size' => 16,
'#maxlength' => 16,
'#description' => t('description'),
);
/* setting_two */
$form['your_module']['products_settings_table']['products_settings_new']['setting_two'] = array(
'#type' => 'textfield',
'#size' => 40,
'#maxlength' => 255,
'#description' => t('description'),
);
/* Submit button */
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save Settings'),
'#name' => 'SubmitButton',
);
return $form;
}
/**
* Custom theme function for a table of products settings
*/
function theme_your_module_products_settings($form) {
$header = array(t('Item Code'), t('Setting One'), t('Setting Two'));
$rows = array();
/* saved rows */
foreach (element_children($form['products_settings']) as $key) {
$row = array();
$row[] = drupal_render($form['products_settings'][$key]['item_code']);
$row[] = drupal_render($form['products_settings'][$key]['setting_one']);
$row[] = drupal_render($form['products_settings'][$key]['setting_two']);
$rows[] = $row;
}
/* new row to add */
$row = array();
$row[] = drupal_render($form['products_settings_new']['item_code']);
$row[] = drupal_render($form['products_settings_new']['setting_one']);
$row[] = drupal_render($form['products_settings_new']['setting_two']);
$rows[] = $row;
$output = theme('table', $header, $rows);
return $output;
}
/**
* Submission function for your_module_admin_settings form.
*/
function your_module_admin_settings_submit($form, &$form_state) {
/* processing changes */
if (isset($form_state['values']['products_settings_table']['products_settings'])) {
foreach ($form_state['values']['products_settings_table']['products_settings'] as $record_id => $data) {
if (empty($data['item_code']) && empty($data['setting_one']) && empty($data['setting_two'])) {
/* delete saved row if all fields are empty */
db_query("DELETE FROM {your_module_settings} WHERE record_id=%d", $record_id);
drupal_set_message(t('Deleted.'), 'status');
}
else {
/* update */
db_query("UPDATE {your_module_settings} SET item_code='%s', setting_one='%s', setting_two='%s' WHERE record_id=%d",
$data['item_code'], $data['setting_one'], $data['setting_two'], $record_id);
}
}
}
/* adding new row */
$item_code = $form_state['values']['products_settings_table']['products_settings_new']['item_code'];
$setting_one = $form_state['values']['products_settings_table']['products_settings_new']['setting_one'];
$setting_two = $form_state['values']['products_settings_table']['products_settings_new']['setting_two'];
if (!empty($item_code) && !empty($setting_one) && !empty($setting_two)) {
db_query("INSERT INTO {your_module_settings} (item_code, setting_one, setting_two) VALUES ('%s', '%s', '%s')",
$item_code, $setting_one, $setting_two);
drupal_set_message(t('Added new setting.'), 'status');
}
drupal_set_message(t('Settings updated.'), 'status');
}
You're generating the fields in the theme function and it will not work because the submit function will only act on the fields generated by your form function.
The correct way is to generate all fields in the form function (basically what you're doing now in the theme function) and render them in the theme using drupal_render.
Since I cannot find any way to access the form/settings variables, inside the theme function
The form is passed to the theme function as an argument, in your case $sender, and that's how you access them.
Here's some code, untested, but you get the idea. Remember that the call $output .= drupal_render($form); is very important because it renders the hidden fields needed by the Form API such as the form_id and the CSRF protection. Without this call submit won't work.
function mymodule_grid_form($form_state) {
$form = array();
$form['variables'] = array();
$result = db_query('SELECT v.name, v.value from {variable} v');
while ($pair = db_fetch_object($result)) {
$form['variables'][$pair->name][$pair->name . '_name'] = array(
'#type' => 'textfield',
'#size' => 30,
'#value' => $pair->name
);
$form['variables'][$pair->name][$pair->name . '_value'] = array(
'#type' => 'textfield',
'#size' => 30,
'#value' => $pair->value
);
}
return $form;
}
function theme_mymodule_grid_form($form) {
$header = array('', t('name'), t('value'));
foreach ($form['variables'] as $variable => $values) {
$row = array('');
$row[] = drupal_render($values[$variable . '_name']);
$row[] = drupal_render($values[$variable . '_value']);
$rows[] = array('data' => $row);
}
$output = theme('table', $header, $rows, array('id' => 'gridErrors'));
$output .= drupal_render($form);
return $output;
}
function mymodule_theme() {
return array(
'mymodule_grid_form' => array(
'arguments' => array('form' => NULL),
),
);
}
i'm still working on my own drupal 7 module, and i'm having some trouble. I'm trying to load database content to dropdown option (select), i have read and write the same code from drupal example, but my database still not loading, only empty option.
what i'm asking is there anything wrong on my code or is there any faster way to load database to dropdown option other than the drupal example???
here the code i'm working on
function prod_entry_load($entry = array()) {
$select = db_select('aa_1122','aa');
$select->fields('aa');
foreach ($entry as $field => $value) {
$select->condition($field, $value);
}
return $select->execute()->fetchAll();
}
function prod(){
return drupal_get_form('prod_form');
}
function prod_form($form_state){
$form = array(
'#prefix' => '<div id="updateform">',
'#suffix' => '</div>',
);
$entries = prod_entry_load();
$keyed_entries = array();
if (empty($entries)) {
$form['no_values'] = array(
'#value' => t("No entries exist in the table dbtng_example table."),
);
return $form;
}
foreach ($entries as $entry) {
$options[$entry->no] = t("#no: #name ", array('#no' => $entry->no, '#name' => $entry->name));
$keyed_entries[$entry->no] = $entry;
}
$default_entry = !empty($form_state['values']['no']) ? $keyed_entries[$form_state['values']['no']] : $entries[0];
$form_state['entries'] = $keyed_entries;
$form['no'] = array(
'#type' => 'select',
'#title' => t('Choose'),
'#default_value' => $default_entry->no,
'#ajax' => array(
'wrapper' => 'updateform',
'callback' => 'prod_form_update_callback',
),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
'#ajax' => array(
'callback' => 'ajax_alert',
),
);
return $form;
}
function prod_form_update_callback($form, $form_state) {
$entry = $form_state['entries'][$form_state['values']['no']];
foreach (array('name') as $item) {
$form[$item]['#value'] = $entry->$item;
}
return $form;
}
You've just forgotten to add the #options key to your select element, the code should read like this:
$form['no'] = array(
'#type' => 'select',
'#title' => t('Choose'),
'#default_value' => $default_entry->no,
'#options' => $options, // This is the bit that was missing
'#ajax' => array(
'wrapper' => 'updateform',
'callback' => 'prod_form_update_callback',
),
);
You could shorten your query/options code slightly using a combination of string concatenation in MySQL and the db fetchAllKeyed() method:
$query = db_select('aa_1122', 'aa')->fields('aa', array('no'));
$query->addExpression("CONCAT(no, ': ', name)", 'display');
$options = $query->execute()->fetchAllKeyed();