I ajax enabled a Select (or other) field but the callback if not being run. The field is inside a field collection. Here is my code.

function MY_MODULE_form_field_collection_item_form_alter(&$form, &$form_state, $form_id){

	if ($form['#bundle']=='field_contract_parties'){
		$form['field_select_or_other']['und']['#options'] = load_select_options();
		$ajax_array = array(
					      'callback' => 'my_callback_function',
					      'wrapper' => 'contacts-replace',
						  'event' => 'change',
					    );				
		$form['field_select_or_other']['und']['#ajax'] = $ajax_array;
					
		$new_properties = array(
							'#prefix' => '<div id="contacts-replace">',
							'#suffix' => '</div>',
						);
		
		$form['field_contact']['und'] = array_merge($form['field_contact']['und'],$new_properties);
	}

}

function my_callback_function($form, $form_state){
	return $form['field_contact']['und'];
}

The above code worked well when i was using a List (text) field instead of a select or other field.
I have tried using 'event' => 'change' but it didn't work either.

Comments

cjgriffin’s picture

Possibly related to this, it appears that #states isn't working on a select_or_other element either. I'm also using it within a field collection.

danielb’s picture

Status: Active » Closed (works as designed)

These aren't things I should have to handle specifically. Just attach the properties directly to the form element (which are children of select_or_other) in a #pre_render callback.
You might also be able to do it via #select_ajax and #other_ajax, etc... but that might depend on what phase of the form you are doing it.

cjgriffin’s picture

FWIW, I got #states to work by adding:

  '#states' => $element['#states'],

to line 104 of select_or_other.module. Might work for #ajax as well (not able to test right now).

jpsolero’s picture

#3 works for #ajax too, It should be:

if (isset($element['#ajax'])) {
  $element['select']['#ajax'] = $element['#ajax'];
}

if (isset($element['#states'])) {
  $element['select']['#states'] = $element['#states'];
}
a.ross’s picture

Issue summary: View changes
Status: Closed (works as designed) » Active

I don't think using a pre-process function to add the #ajax stuff works. The AJAX callback system relies on it being defined during form creation, not during rendering. This is quite an annoying bug, which means having to create extremely ugly workarounds.

danithaca’s picture

both #select_ajax and #other_ajax worked. thanks!

jaskho’s picture

Re #select_ajax and #other_ajax (which I didn't immediately follow from the previous comments)...

The select_or_other module looks for any element property prefixed with "select_" or "other_" and applies it to the appropriate widget fields:


/**
 * In select_or_other.module
 */

function select_or_other_element_process() {

  // ... 

  // Populate properties set specifically as #select_property or #other_property
  $sub_elements = array('select', 'other');
  foreach ($sub_elements as $sub_element) {
    foreach ($element as $key => $value) {
    if (strpos($key, '#' . $sub_element . '_') === 0) {
        $element[$sub_element][str_replace('#' . $sub_element . '_', '#', $key)] = $value;
      }
    }
    // ...
  }

  // ...

So a '#select_ajax' key on the field's element array gets turned into an '#ajax' key on the elements generated by the widget downstream.

And here, just for fun, is the code that worked for me:

/**
 * Implements hook_field_widget_WIDGET_TYPE_form_alter().
 */
my_module_field_widget_select_or_other_buttons_form_alter(&$element, &$form_state, $context) {
  $element['#select_ajax'] = array(
     'callback' => 'my_module_ajax_callback',
  );     
}
legolasbo’s picture

@Jaskho perhaps you could document this as the first documentation in select_or_other.api.php

sassafrass’s picture

I was able to use #select_ajax to get my ajax callback triggered. However, I was not able to get the #states to work. I tried both suggestions in #3 and #4 above, but it didn't work. :(

My Select or Other field:

// To fix: Select or other doesn't seem to work with #states. 
  $form['discovery_information']['reference_source_information']['reference_source_type'] = array(
    '#type' => 'select_or_other',
    '#select_type' => 'select',
    '#title' => 'Reference Type',
    '#required' => TRUE,
    '#options' => array(
      'website' => t('Website'),
      'media_print' => t('Media – Print'),
      'media_broadcast' => t('Media – Broadcast'),
      'media_electronic' => t('Media – Electronic'),
      'scientific_journal' => t('Scientific Journal'),
      'scientific_presentation' => t('Scientific Presentation'),
      'enforcement_report' => t('Enforcement Report'),
      'application_note' => t('Application Note'),
      'book_chapter' => t('Book/Chapter'),
      'personal_communication' => t('Personal Communication'),
    ),
    '#other' => t('Other (please type a value)'),   // Text to show as 'other' option
    '#other_unknown_defaults' => 'other', // If the #default_value is not a valid choice in #options, what should we do? 
    '#select_ajax' => array(
      'callback' => 'create_reference_source_labels',
      'wrapper' => 'basic_reference_source_info',
    ),
);

My #states field that depends on the Select or Other field:

  $form['discovery_information']['reference_source_information']['secondary_title'] = array(
    '#type' => 'textfield',
    '#title' => 'Magazine/Newspaper Title',
    '#description' => '',
    '#states' => array(
      'visible' => array(
         ':input[name="discovery_information[reference_source_information][reference_source_type]"]' => array('value' => 'media_print'),
      ),
    ),
  );

sassafrass’s picture

Okay, I found my mistake(s). I am now able to get #3/#4 working for #states by

1. Adding:

if (isset($element['#states'])) {
    $element['select']['#states'] = $element['#states'];
}

to the select_or_other.module file.

2. First mistake: Incorrect jquery selector. Needed to add '[select]' to the end:

name="discovery_information[reference_source_information][reference_source_type][select]"]'

3. Second mistake: I was rewriting the dependent field in my ajax callback. Don't DO that! :-)

Thank-you cjgriffin and jpsolero for the suggestions.

legolasbo’s picture

1. Adding:

if (isset($element['#states'])) {
$element['select']['#states'] = $element['#states'];
}
to the select_or_other.module file.

You don't have to hack the select_or_other.module file to do this. you can just add #select_states to your element and it will be passed along just like #select_ajax. Any #select_* element in the array will be passed to the select form element, any #other_* array element will be passed to the other form element.

sassafrass’s picture

As legolasbo suggested in #11, I removed the hack and replaced '#states' with '#select_states' and it works if I have a single condition. But if I have multiple conditions "AND"ed together, it doesn't get triggered the first time a state is changed, only subsequent state changes.

legolasbo’s picture

Status: Active » Closed (works as designed)

Closing this back up because the #select_states and #other_states are passed along correctly.

sassafrass, please open a new issue for the state bug you are experiencing with clear steps to reproduce the issue.