I'm trying to add ajax functionality for two fields (field1 and field2) at the same time dependent on a third field (field3).

If I understand the example from examples_module right, field1 and field2 must be in a fieldset.
So I added a fieldgroup "test" through contenttype UI and created field1 and field2 in this group.

But how to find the ajax wrapper id for this new fieldgroup (fieldset) ?
Seems like it is "node_test_form_group_test"

How to return the form element for this fieldgroup in ajax_callback_function ?
return form['group_test'] doesn't work

Seems like group_test is an object, not an array

CommentFileSizeAuthor
#3 contenttype_testgroup.JPG32.34 KBMicha1111
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Stalski’s picture

Then you are looking at the wrong place. The field group "elements" are there as well, the groups indeed is the objects only

Stalski’s picture

Did you manage to find the elements in the nested form tree?

Micha1111’s picture

FileSize
32.34 KB

Unfortunately not, I can't find the right place.

On screenshot, you can see my setup for contenttype "testgruppe"

If I print out the form array with "print_r", there are only the following parts for fieldgroup group_test:

[#groups] => Array
        (
            [group_test] => stdClass Object
                (
                    [id] => 1
                    [identifier] => group_test|node|testgruppe|form
                    [group_name] => group_test
                    [entity_type] => node
                    [bundle] => testgruppe
                    ....

[#fieldgroups] => Array
        (
            [group_test] => stdClass Object
                (
                    [id] => 1
                    [identifier] => group_test|node|testgruppe|form
                    [group_name] => group_test
                    [entity_type] => node
                    [bundle] => testgruppe
                    [mode] => form
                    [parent_name] => 
                    [table] => field_group
                    ....

[#group_children] => Array
        (
            [field_feld1] => group_test
            [field_feld2] => group_test
        )

I think, the right way to return a form fieldset in ajax_callback function is: return $form['group_test'];
and
There should be a wrapper id, set by #prefix and #suffix for this fieldset.

Stalski’s picture

Status: Active » Postponed (maintainer needs more info)

Can you provide the code how you are ajaxing the form fields (groups). I don't really got a clue what you are trying to do .

for the ID , indeed it's "node_test_form_group_test", meaning [entity]_[entity-type]_[view-mode]_[group-name].
The form itself has indeed #groups and #group_children and everything, but those are properties (# prefixed). You need to look in the root for the group. It is there otherwise the group would not render at all.

Micha1111’s picture

In core 7.x, it's not possible to create fieldsets through UI.
But if you want to change two fields in a form dependent on input of a third field with AJAX, it is required that these two fields are in a fieldset.

Fields 1,2,3 are created through contenttype UI -> manage fields.
Here is the code (not all, but the way), to add AJAX for feld3 by a custom module, named "test".
If input of feld3 changed, the fieldset is rebuilded and feld1 and feld2 are changed too.

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

switch ($form_id) {
    
	case 'testgruppe_node_form':
	
	$form['feld3'][LANGUAGE_NONE] += array(
	'#ajax' => array(
              'callback' => 'test_callback',
              'wrapper' => 'testfieldset',
              ),
	);
	
	$form['group_test'] = array(    
		'#type' => 'fieldset',    
		'#title' => t('Testgruppe'),    
		'#collapsible' => TRUE,    
		'#collapsed' => FALSE,
		'#weight' => 4,
		'#prefix' => '<div id="testfieldset">',
		'#suffix' => '</div>',	
		);
		
	$uebergabewert = code for $uebergabewert	
	
                          $form['feld1'] = array(    
		'#type' => 'field_type',    
		'#title' => t('Feld1'),
		'#default_value' => _ajax_testwert1($uebergabewert),	
		);
                           $form['group_test']['feld1'] = $form['feld1'];
                           $form['feld1'] = array('#language' => NULL);
		
	            $form['feld2'] = array(    
		'#type' => 'field_type',    
		'#title' => t('Feld2'),
		'#default_value' => _ajax_testwert2($uebergabewert),
		);
                          $form['group_test']['feld2'] = $form['feld2'];
                          $form['feld2'] = array('#language' => NULL);
		
	break;
	
	default:
	break;
	
	}
}

function test_callback($form, $form_state) {
    return $form['group_test'];
}


function _ajax_testwert1 ($testwert) {
	return "Der Wert ist " . $testwert;
	}

function _ajax_testwert2 ($testwert) {
	$neuerwert = $testwert + 5;
	return "Der Wert ist " . $neuerwert;
	}

In other words:
add AJAX to field3
create a new formfieldset "group_test"

Call _ajax_testwert functions to calculate the new default_values for feld1 and feld2

change default_value of feld1 and feld2 at the same time by rebuilding the fieldset "group_test".

To do that, you have to move feld1 and feld2 into a fieldset and unset the old form fields from root of form array !!
code of ajax_examples_module shows this way

and works fine !!

I thougth, that there is no need to move feld1 and feld2 into a new fieldset, if I create the fieldset with your module through contenttype UI.
And perhaps there is a way to add a new wrapper_id with adding a #prefix and #suffix for this fieldset.

Micha1111’s picture

no idea ?

or

not possible ?

Anonymous’s picture

With Drupal ajax framework, you provide a wrapper div around form elements you want to replace with your ajax callback.

Using a traditional form API element, you add a #prefix and #suffix attribute to the element array. For example, with a node title field, you would add the following code in a hook to establish the wrapper div:

$form['title']['#prefix'] = '<div id="my-wrapper">';
$form['title']['#suffix'] = '</div>';

I think the OP is wondering if it is possible to add this wrapper div to a fieldset created with the Field Group module, and if so how they would add the attributes to the object located in $form.

Ajax Framework info - http://api.drupal.org/api/drupal/includes--ajax.inc/group/ajax

Stalski’s picture

Status: Postponed (maintainer needs more info) » Closed (won't fix)

I actually completely follow ausrick on this. You could use field_group to add the wrapper div, but then again the ajax framework works with suffix/prefix.
I am most in favour of closing this issue as "won't fix" since I think this can and needs to be done by custom coding. There are modules available (ajax_*) that can do this for you, but field_group will not be the one. Simply because it does not work with prefix and suffixes but with real form elements. The other reason is that creating a system like ajax framework but different is a bit over the top.

The intention of this module is to be a stable field wrapper module, for theming or UX purposes. Other reasons will mostly not be added nor maintained.

ricovandevin’s picture

Title: How to ajaxfy fields in field_group ? » How to render a single field group from a forms array?
Component: Miscellaneous » Documentation
Status: Closed (won't fix) » Active

This was a support request from to OP and not a feature request so why close it as a won't fix? I have the same question as the OP. Maybe I can explain it better.

The question is how to render a single field group from a forms array? This is needed in the ajax callback. I have a quite complicated structure with nested field groups. One of these has to be refreshed once the value of a select list get changed (see also http://drupal.org/node/1343468#comment-5298068).

In #4 it is stated that

You need to look in the root for the group.

. This is not true. As mentioned in #3 information about the field groups is only available in ['#groups'], ['#fieldgroups'] and ['#group_children']. Only the fields seem to have entries in the root of the forms array and not the field groups.

ricovandevin’s picture

Version: 7.x-1.x-dev » 7.x-1.1

BTW I'm using version 7.x-1.1 of the field_groups module in Drupal 7.9.

Stalski’s picture

You say it is not true? I can see the groups in the root of the element. The fieldgroup elements are ofcourse nested in the normal drupal built. Big difference between the groups (which are Ctools exportable objects) and the elements (which are elements with # properties).

If I can't set it to "won't fix", what do you expect me to do then? It is possible, but it's done by custom coding.
The only tip I can give you is to look into the patch in #1278618: Panels integration where Hydra is trying to render a field_group as standalone.

ricovandevin’s picture

For me, just like Micha1111 the only references to group_basic_relation (the name of the group I want to render in my case) occur in the ['#groups'], ['#fieldgroups'] and ['#group_children'] and nowhere else in de $form array within my hook_form_alter implementation.

I'll have a look at the patch in #1278618: panels integration to see if that can point me in the right direction.

Stalski’s picture

I am starting to be interested in the use cases. Can someone point me out where this is the best solution to render a set of fields? (Meaning fieldgroup nests fields, but why should the responsibility of the rendering move to the fieldgroup module?)

- Edit - I see panels integration as an edge case

josesanmartin’s picture

Micha1111 and whoever find this on Google. This works for me:

    $processed_form = $form;
    $processed_form = field_group_build_pre_render($processed_form);
    render($processed_form[$group_name]);
wwedding’s picture

To clarify for anyone else, too...

Micha1111 was simply trying to ask how to return a field group element in an ajax callback (as used in Drupal's AJAX API). It is pretty challenging to figure out because for a regular field you'd just do something like...

 function ajax_callback($form, &$form_state) {
  return $form['field_name'];   
}

And in a form alter there'd be something like...

 function ajax_form_alter($form, &$form_state) {
  $form['field_name']['#prefix'] = '<div id="field_name_wrapper">';
  $form['field_name']['#suffix'] = '</div>';
}

... which would be referenced in another element's #ajax array.

Unfortunately, the render elements for a field_group don't make this easy or possible. They're pretty a-typical form elements and you can't do a lot of things you'd normally expect to be able to do.

There wasn't any request to add functionality or features to the field_groups module, just as request for guidance (which someone has finally given over 2 years later :( Sorry Michae1111! ).

#14's way to do might work but it really doesn't feel like "The Drupal Way" to do it.

drx’s picture

I was another person who was simply trying to return a field group element in an ajax callback. In my case, I wanted to prepopulate the fields in a fieldgroup based on a value chosen in a select box. I really (really, really) wish I had come across this post before I wasted a lot of time trying to do something that should be pretty easy. For others who come to this post before wasting time...I ended up using the Field collection module. The collection of fields behaves like a field and the ajax replacement works like you expect it to.

gbirch’s picture

Issue summary: View changes

Thank you very much to Jose San Martin (#14) for finding the answer. However, since field_group has been updated, here are the revisions you need to make it work (as of version 7.x-1.4):

function mymodule_callback($form, $form_state) {

  $form = field_group_form_pre_render($form); // note change in function name

  return drupal_render($form['group_XXX']); // the pre_rendering confuses the rendering otherwise performed by the Ajax API, so you have to return the rendered HTML.

}

I hope that saves someone an hour or two.

sassafrass’s picture

Thank-you Jose San Martin (#14) and gbirch (#17) for pointing me in the general direction. I have been trying to figure this out all day but still need some more guidance.

Two questions to start:

1. Is the function mymodule_callback($form, $form_state) the function that is called by the triggered ajax?
2. And...are the #prefix and #suffix no longer needed? If not, what do I do with 'wrapper' in the ajax array?

For example:

$form['field_reference_source_type']['und']['#ajax'] = array(
		'callback' => 'mymodule_callback',
		'wrapper' => 'id_in_prefix_div_tag',
	);
gbirch’s picture

sassafrass: Yes, mymodule_callback is the function that ultimately delivers the revised HTML. As to your second question, it's a little complicated. It's been a while, and there may be other, less ornate ways to do it, but here's what I did:

1. Using manage fields for the relevant content type, I added two nested field groups to the content type, named "group_ajax" and "group_details". The fields to be updated are inside group_details. The outer, group_ajax field group is of type HTML element, but the actual element is a fieldset. This outer field group has id="ajax-wrapper" in the attributes of the fieldset settings. I don't remember why I didn't use the id field. The outer field group is effectively supplying the prefix and suffix.

2. I ended up having to edit the callback code a bit because the id was getting changed if ajax fired more than once.

  // field_group makes this difficult
  $form = field_group_form_pre_render($form);
  // reset the id of the ajax group, which otherwise gets a counter appended by drupal_html_id
  $wrap_id = 'ajax-wrapper';
  $form['group_ajax']['#id'] = $wrap_id;
  $form['group_ajax']['#prefix'] = str_replace($wrap_id.'--2', $wrap_id, $form['group_ajax']['#prefix']);
  return drupal_render($form['group_ajax']);

3. The array you append to the triggering element then looks like this:

array(
      'wrapper' => 'ajax-wrapper', // ajax-wrapper id is set in Manage Fields
      'callback' => 'mymodule_callback',
    );
gruda’s picture

Thanks for this. In some cases, the id of the group fieldset cannot be set because Manage Fields is not available (in my case, user registration form). You'll have to do something like this:

$form['#groups']['group_user_profile']->format_settings['instance_settings']['id'] = 'youridhere';
mahimajulka’s picture

I want to add callback to a field present inside a field group. Not able to figure out. Can you guys help ?
Adding Ajax on entire field group elements is working. But I need solution for particular field only

udaf’s picture

function mdd_form_object_node_form_alter(&$form, &$form_state, $form_id) {
  $form['field_sale_type']['und']['#ajax'] = array(
    'callback' => 'mdd_object_field_sale_type_onchange',
    'wrapper' => 'group-sale',
  );
  $form['field_sale_type']['und']['#prefix'] = rand(1,100000);
}

function mdd_object_field_sale_type_onchange($form, $form_state){
  field_group_fields_nest($form);
  return $form['group_sale'];
}

function mdd_field_group_pre_render(&$element, &$group, & $form) {
  if($form['#form_id'] == 'object_node_form'){
    $form['group_sale']['#prefix'] = '<div id="group-sale">';
    $form['group_sale']['#suffix'] = '</div>';
  }
}
steinmb’s picture

Status: Active » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.