Last active
January 24, 2017 03:24
-
-
Save jackrabbithanna/71e407d5ffb089b4a07778b47a5629b8 to your computer and use it in GitHub Desktop.
Custom FAPI multivalued element type, 2 column grid of textfields, ajax add and remove
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Implements hook_theme(). | |
* | |
* @return array | |
*/ | |
function webform_multi_theme() { | |
return array( | |
'webform_multi_url_params_field' => array( | |
'render element' => 'element', | |
), | |
); | |
} | |
/** | |
* Implements hook_element_info(). | |
* | |
* @return mixed | |
*/ | |
function webform_multi_element_info() { | |
$elements['webform_multi_url_params'] = array( | |
'#default_value' => '', | |
'#input' => TRUE, | |
'#process' => array('webform_multi_url_params_element_process'), | |
'#theme' => array('webform_multi_url_params_field'), | |
'#theme_wrappers' => array('form_element'), | |
'#tree' => TRUE, | |
'#value_callback' => 'webform_multi_url_params_element_value_callback', | |
); | |
return $elements; | |
} | |
/** | |
* Process callback for the webform_multi_url_params FAPI element | |
* | |
* @param $element | |
* @param $form_state | |
* @param $complete_form | |
*/ | |
function webform_multi_url_params_element_process($element, $form_state, $complete_form) { | |
$element_name = $element['#name']; | |
preg_match_all("/\[([^\]]*)\]/", $element_name, $matches); | |
if( count($matches) ) { | |
$temp_name = end($matches); | |
if(!empty($temp_name)) { | |
$element_name = $temp_name[0]; | |
} | |
} | |
// get settings from either form state storage, form state values, or from stored db values or variable values | |
if(!empty($form_state['webform_multi_url_param_settings'][$element_name])) { | |
$url_param_settings = $form_state['webform_multi_url_param_settings'][$element_name]; | |
} | |
else { | |
//first look for passed defaults | |
if(empty($form_state['input']) && !empty($element['#default_value'])) { | |
$url_param_settings = array(); | |
if(!empty($element['#default_value'])) { | |
foreach($element['#default_value']['webform_multi_url_params']['url_params'] as $count => $param) { | |
$url_param_settings[$count] = $param['param']; | |
} | |
} | |
$url_param_settings[] = array('source_param' => '', 'redirect_param' => ''); | |
} | |
else { | |
// if none, then setup a blank item | |
$url_param_settings = array( | |
0 => array('source_param' => '', 'redirect_param' => ''), | |
); | |
} | |
} | |
$element['webform_multi_url_params']['url_params'] = array( | |
'#type' => 'container', | |
'#tree' => TRUE, | |
'#prefix' => '<div id="webform-multi-url-params_' . $element_name . '">', | |
'#suffix' => '</div>', | |
'#attributes' => array( | |
'class' => array( | |
'webform-multi-url-params-container', | |
), | |
), | |
); | |
foreach($url_param_settings as $count => $settings) { | |
$element['webform_multi_url_params']['url_params'][$count]['param'] = array( | |
'#type' => 'container', | |
'#tree' => TRUE, | |
'#attributes' => array( | |
'class' => array('webform-multi-url-param-row'), | |
), | |
); | |
$element['webform_multi_url_params']['url_params'][$count]['param']['source_param'] = array( | |
'#type' => 'textfield', | |
'#size' => 30, | |
'#required' => $element['#required'], | |
'#title' => t('Source Parameter'), | |
'#title_display' => 'invisible', | |
'#theme_wrappers' => array(), | |
'#attributes' => array('placeholder' => 'source parameter'), | |
'#default_value' => $settings['source_param'], | |
); | |
$element['webform_multi_url_params']['url_params'][$count]['param']['redirect_param'] = array( | |
'#type' => 'textfield', | |
'#size' => 30, | |
'#required' => $element['#required'], | |
'#title' => t('Redirect Parameter'), | |
'#title_display' => 'invisible', | |
'#theme_wrappers' => array(), | |
'#attributes' => array('placeholder' => 'redirect parameter'), | |
'#default_value' => $settings['redirect_param'], | |
); | |
$element['webform_multi_url_params']['url_params'][$count]['param']['remove_param' . $count] = array( | |
'#parent_element_name' => $element_name, | |
'#parent_element_parents' => $element['#parents'], | |
'#name' => 'url-param-remove|' . $count . '|' . $element_name, | |
'#id' => 'url-param-remove-' . $count . '-' . $element_name, | |
'#type' => 'image_button', | |
'#button_type' => 'image-button', | |
'#src' => drupal_get_path('module', 'webform_multi') . '/img/delete.png', | |
'#default_value' => t('Remove'), | |
'#limit_validation_errors' => array(), | |
'#submit' => array('webform_multi_url_param_element_add_remove_value_submit'), | |
'#ajax' => array( | |
'wrapper' => 'webform-multi-url-params_' . $element_name, | |
'callback' => 'webform_multi_url_param_element_ajax_callback', | |
), | |
); | |
} | |
$element['webform_multi_url_params']['add_param_setting'] = array( | |
'#parent_element_name' => $element_name, | |
'#name' => 'add-param-setting' . '_' . $element_name, | |
'#id' => 'add-param-setting' . '_' . $element_name, | |
'#type' => 'submit', | |
'#default_value' => t('Add'), | |
'#submit' => array('webform_multi_url_param_element_add_remove_value_submit'), | |
'#ajax' => array( | |
'wrapper' => 'webform-multi-url-params_' . $element_name, | |
'callback' => 'webform_multi_url_param_element_ajax_callback', | |
), | |
); | |
$element['#attached']['css'][] = drupal_get_path('module', 'webform_multi') . '/css/url-param-element.css'; | |
return $element; | |
} | |
/** | |
* Add and Remove button submit callback | |
* | |
* @param $form | |
* @param $form_state | |
*/ | |
function webform_multi_url_param_element_add_remove_value_submit($form, &$form_state) { | |
if(!empty($_POST['_triggering_element_name'])) { | |
if(!preg_match('/^[a-zA-Z0-9_\-\|]+$/', $_POST['_triggering_element_name'])) { | |
return; | |
} | |
} | |
else { | |
$_POST['_triggering_element_name'] = $form_state['triggering_element']['#name']; | |
} | |
if (strpos($_POST['_triggering_element_name'], "url-param-remove") === 0) { | |
$name_array = explode('|', $_POST['_triggering_element_name']); | |
$index = $name_array[1]; | |
$parent_element_name = $name_array[2]; | |
$parents = $form_state['triggering_element']['#array_parents']; | |
//need this bit incase there are 2 element on the form and drupal gets the triggering_element wrong | |
foreach($parents as $count => $parent) { | |
if($parent == 'webform_multi_url_params') { | |
$parents[$count-1] = $parent_element_name; | |
break; | |
} | |
} | |
if($form_state['triggering_element']['#name'] == 'add-param-setting') { | |
array_pop($parents); | |
$parents[] = $parent_element_name; | |
} | |
else { | |
array_pop($parents); | |
array_pop($parents); | |
array_pop($parents); | |
} | |
if(isset($form_state['input'][$parents[0]])) { | |
$input =& drupal_array_get_nested_value($form_state['input'], $parents); | |
} | |
else { | |
$first_parent = array_shift($parents); | |
$input =& drupal_array_get_nested_value($form_state['input'], $parents); | |
} | |
unset($input[$index]); | |
$input = array_values($input); | |
drupal_array_set_nested_value($form_state['input'], $parents, $input); | |
$form_state['webform_multi_url_param_settings'][$parent_element_name] = array(); | |
foreach($input as $count => $settings) { | |
$form_state['webform_multi_url_param_settings'][$parent_element_name][$count] = $settings['param']; | |
} | |
} | |
elseif(strpos($_POST['_triggering_element_name'], "add-param-setting") === 0) { | |
$parents = $form_state['triggering_element']['#parents']; | |
array_pop($parents); | |
$input = drupal_array_get_nested_value($form_state['input'], $parents); | |
$form_state['webform_multi_url_param_settings'][$form_state['triggering_element']['#parent_element_name']] = array(); | |
foreach($input['url_params'] as $count => $settings) { | |
$form_state['webform_multi_url_param_settings'][$form_state['triggering_element']['#parent_element_name']][$count] = $settings['param']; | |
} | |
$form_state['webform_multi_url_param_settings'][$form_state['triggering_element']['#parent_element_name']][] = array('source_param' => '', 'redirect_param' => ''); | |
} | |
$form_state['rebuild'] = TRUE; | |
} | |
/** | |
* Add and remove button ajax callback | |
* | |
* @param $form | |
* @param $form_state | |
* @return array | |
*/ | |
function webform_multi_url_param_element_ajax_callback($form, &$form_state) { | |
if(!empty($_POST['_triggering_element_name'])) { | |
if(!preg_match('/^[a-zA-Z0-9_\-\|]+$/', $_POST['_triggering_element_name'])) { | |
return; | |
} | |
} | |
else { | |
$_POST['_triggering_element_name'] = $form_state['triggering_element']['#name']; | |
} | |
$commands = array(); | |
if (strpos($_POST['_triggering_element_name'], "url-param-remove") === 0) { | |
$name_array = explode('|', $_POST['_triggering_element_name']); | |
$index = $name_array[1]; | |
$parent_element_name = $name_array[2]; | |
$parents = $form_state['triggering_element']['#array_parents']; | |
//need this bit incase there are 2 element on the form and drupal gets the triggering_element wrong | |
foreach($parents as $count => $parent) { | |
if($parent == 'webform_multi_url_params') { | |
$parents[$count-1] = $parent_element_name; | |
break; | |
} | |
} | |
if(strpos($form_state['triggering_element']['#name'], 'add-param-setting') === 0) { | |
array_pop($parents); | |
} | |
else { | |
array_pop($parents); | |
array_pop($parents); | |
array_pop($parents); | |
} | |
$element = drupal_array_get_nested_value($form, $parents); | |
if($form_state['triggering_element']['#name'] == 'add-param-setting') { | |
$commands[] = ajax_command_html('#webform-multi-url-params_' . $parent_element_name, render($element['url_params'])); | |
} | |
else { | |
$commands[] = ajax_command_html('#webform-multi-url-params_' . $parent_element_name, render($element)); | |
} | |
} | |
elseif(strpos($_POST['_triggering_element_name'], "add-param-setting") === 0) { | |
$parents = $form_state['triggering_element']['#array_parents']; | |
array_pop($parents); | |
$element = drupal_array_get_nested_value($form, $parents); | |
$commands[] = ajax_command_html('#webform-multi-url-params_' . $form_state['triggering_element']['#parent_element_name'], render($element['url_params'])); | |
} | |
if (!empty($commands)) { | |
$commands[] = ajax_command_prepend('#webform-multi-url-params_' . $form_state['triggering_element']['#parent_element_name'], '<div id="messages">' . theme('status_messages') . '</div>'); | |
return array('#type' => 'ajax', '#commands' => $commands); | |
} | |
} | |
/** | |
* Theme callback for the webform_multi_url_params FAPI element type | |
* | |
* @param $variables | |
* @return string | |
*/ | |
function webform_multi_url_params_field($variables) { | |
$element = $variables['element']; | |
$output = drupal_render($element); | |
return $output; | |
} | |
/** | |
* Value callback for the webform_multi_url_params FAPI element type | |
* | |
* @param $element | |
* @param bool $input | |
* @param $form_state | |
* @return bool|void | |
*/ | |
function webform_multi_url_params_element_value_callback($element, $input = FALSE, &$form_state) { | |
if ($input !== FALSE) { | |
foreach($input['webform_multi_url_params']['url_params'] as $count => $param) { | |
if ($input['webform_multi_url_params']['url_params'][$count]['param']['source_param'] && !$input['webform_multi_url_params']['url_params'][$count]['param']['redirect_param']) { | |
$input['webform_multi_url_params']['url_params'][$count]['param']['source_param'] = ''; | |
} | |
if ($input['webform_multi_url_params']['url_params'][$count]['param']['redirect_param'] && !$input['webform_multi_url_params']['url_params'][$count]['param']['source_param']) { | |
$input['webform_multi_url_params']['url_params'][$count]['param']['redirect_param'] = ''; | |
} | |
} | |
return $input; | |
} | |
elseif (!empty($element['#default_value'])) { | |
return $element['#default_value']; | |
} | |
return; | |
} |
Keep playing with it, works good now for being in a parent #tree or not, multiple widgets on the same page, need to format the #default_value non optimally IMO
Its because the $element['webform_multi_url_params']['url_params'] container has #tree = TRUE
and the row container, 'params' also has #tree true
I would have not had that but I needed a way to control an id so I could use the ajax, but maybe it was unnecessary?
Is the two containers that the ajaxified buttons go in with #tree = TRUE related to sometimes Drupal not getting the $form_state['triggering_element'] right? This necessitated all the logic looking at $_POST['triggering_element_name']......
$form['redirect_settings']['url_params'] = array(
'#type' => 'webform_multi_url_params',
'#title' => 'URL Redirect Parameters',
'#required' => FALSE,
'#default_value' => array(
'webform_multi_url_params' => array(
'url_params' => array(
0 => array('params' => array('source_param' => 'someParam', 'redirect_param' => 'someParam')),
),
),
),
);
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can add multiple form elements of this custom type 'webform_multi_url_params' and the ajax works right
Although this element type was created for a custom webform integration module I am writing, but doesn't make a webform component type. This is a FAPI element type, like 'textfield', or 'select'