Hi

I am trying to get this working on my drupal site. Although the form displays correctly with the "add new section" links etc, when I submit the form back the additional parameters are not submitted. What is strange is that they do not even appear in the $_POST array even though the field_name-rc record count variable does. Any ideas what might be going wrong?

My form code is:

/* START REPEATING LOCATION HIGHLIGHTS SECTION */
$form['location_highlights'] = array(
'#type' => 'fieldset',
'#title' => t('Highlights'),
'#tree' => TRUE,
'#attributes' => array('id' => 'location_highlights', 'class' => 'repeat'),
);
$form['location_highlights']['description'] = array(
'#type'=> 'textfield',
'#title' => t('Description'),
'#default_value' => $node->title,
'#required' => TRUE,
'#description' => t('Describe the highlight.'),
);
$form['location_highlights']['distance'] = array(
'#type'=> 'textfield',
'#title' => t('Distance'),
'#default_value' => $node->title,
'#required' => TRUE,
'#description' => t('How far is the highlight from the location.'),
);
/* END REPEATING LOCATION HIGHLIGHTS SECTION */

Thanks for you help and for bringing this great library into the already great Drupal framework!

Dave

Comments

nedjo’s picture

I haven't tried the repeat behaviour in Drupal. But with what you have, it looks like your duplicates might just overwrite the existing elements. I'd suggest this: try to ensure that the whole thing that you're repeating is itself part of a #tree. E.g.:

$form['highlights'] = array(
  '#tree' => TRUE
);
/* START REPEATING LOCATION HIGHLIGHTS SECTION */
$form['highlights']['location_highlights'] = array(
'#type' => 'fieldset',
'#title' => t('Highlights'),
'#tree' => TRUE,
'#attributes' => array('id' => 'location_highlights', 'class' => 'repeat'),
);
$form['highlights']['location_highlights']['description'] = array(
'#type'=> 'textfield',
'#title' => t('Description'),
'#default_value' => $node->title,
'#required' => TRUE,
'#description' => t('Describe the highlight.'),
);
$form['highlights']['location_highlights']['distance'] = array(
'#type'=> 'textfield',
'#title' => t('Distance'),
'#default_value' => $node->title,
'#required' => TRUE,
'#description' => t('How far is the highlight from the location.'),
);
/* END REPEATING LOCATION HIGHLIGHTS SECTION */

Does that work?

_-dave-_’s picture

Hi

Thanks for the swift response!

Alas that does not work but you might be on to something - I put different values into each of the form sections and the second one which has a html element id of:

edit-highlights-location_highlights-distance-2

is being returned as:

$_POST['edit']['highlights']['location_highlights']['distance']

So it looks like the existing elements are being overwritten. Is this down to the way Drupal handles form variables? Any ideas on a fix?

Thanks
Dave

nedjo’s picture

Don't have time today to look into this. You could study a plain wForms example and then the Drupal example and compare the differences. Use Firefox to highlight the elements after they've been repeated and then right click for "view selected source"--that way you see what's been rendered via JS. What is different in the plain wForms vs. Drupal?

_-dave-_’s picture

Hi

No worries if your busy today.

I have checked that and the html produced by the js is the same in both example cases. From some investigation it is being caused by a clash between wforms and drupal. Because drupal uses the name attribute to return arrays:

name="edit[location_highlights][description]"

wforms will just rename this as:

name="edit[location_highlights][description]-2"

which is the parsed by php back to:

$_POST['edit'][location_highlights][description]

over wrighting the original...

If you have any ideas when you have a free moment I would be eternally grateful. Will see if the wforms developer as any suggestions as well.

Thanks for you help.

Dave

_-dave-_’s picture

Ok, managed to fix it although not the most elegent solution...

First, you can declare an array through the forms api as follows:

  /* START  LOCATION HIGHLIGHTS SECTION */

  $form['location_highlights'] = array(
    '#type' => 'fieldset',
    '#title' => t('Highlights'),
    '#tree' => TRUE,
    '#attributes' => array('id' => 'location_highlights', 'class' => 'repeat'),
  );
  $form['location_highlights']['0'] = array(
    '#type' => 'fieldset',       
    '#tree' => TRUE,                                                           
  );        
  $form['location_highlights']['0']['description'] = array(
    '#type'=> 'textfield',
    '#title' => t('Description'),
    '#default_value' => $node->title,
    '#required' => TRUE,
    '#description' => t('Describe the highlight.'),
  );
  $form['location_highlights']['0']['distance'] = array(
    '#type'=> 'textfield',
    '#title' => t('Distance'),
    '#default_value' => $node->title,
    '#required' => TRUE,
    '#description' => t('How far is the highlight from the location.'),
  );
  /* END  LOCATION HIGHLIGHTS SECTION */

This works fine although the id will now have a "--" in the middle(!)

then...

Changed the line (about 262) in wforms.js from:

var value = attribute.nodeValue + idSuffix;

to:

if (attribute.nodeName.toLowerCase() == "name") {
  var value = attribute.nodeValue.replace("[0]", ["+parseInt(counterField.value+1)+"]")
} else {
  var value = attribute.nodeValue + idSuffix;
} 

Which updates any array decleration in the name attribute with the current row count.

NB: This change was made in the verbose version of wforms.

Strangely drupal will still remove the array when parsing it back into the node however the $_POST array keeps it intact. Will see if i can get to the bottom of the drupal issue...

Dave

Thanks
Dave

milosh’s picture

Title: Repeat Form Section » Idea to go further

The reason, why Drupal won't parse pack the full array of repeated form values, but only one the last value seems to be simple -- the form itself will be built based on the module_form hook and then the $_POST values are passed into this form.

In other words -- after submitting the form with multiplied fields, the form structure will be built based on $form['location_highlights']['0']['description'] . As there is only one subarray ['0'] in module_form hook, the code presumes, that there is only one collection of data.

Therefore, hook module_form code needs to be changed to build form like $form['location_highlights'][$i]['description'] , where $i =~ count($_POST['location_highlights']) or $i =~ count(query_rows['location_highlights'])

milosh’s picture

Title: Idea to go further » Simple fix

There is simple fix to the code above, that corrects the code, so all posted values get into $node->form:

/* START LOCATION HIGHLIGHTS SECTION */

$form['location_highlights'] = array(
'#type' => 'fieldset',
'#title' => t('Highlights'),
'#tree' => TRUE,
'#attributes' => array('id' => 'location_highlights', 'class' => 'repeat'),
);

// how many rows there should be?
// ... how many rows, when node is submitted?
if (is_array($_POST['location_highlights'])) {
  // how many rows were submited
  $nr = count($_POST['location_highlights'])-1;
} else {
  // default -- have just one row
  $nr = 0;
} // end if

// ... how many rows, when node is viewed from the database?
// ... similar check to be added //

// loop the form:
for ($i=0; $i<=$nr; $i++) {
$form['location_highlights'][$i] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
);
$form['location_highlights'][$i]['description'] = array(
'#type'=> 'textfield',
'#title' => t('Description'),
'#default_value' => $node->title,
'#required' => TRUE,
'#description' => t('Describe the highlight.'),
);
$form['location_highlights'][$i]['distance'] = array(
'#type'=> 'textfield',
'#title' => t('Distance'),
'#default_value' => $node->title,
'#required' => TRUE,
'#description' => t('How far is the highlight from the location.'),
);
} // end for loop
/* END LOCATION HIGHLIGHTS SECTION */
milosh’s picture

small typo-fix to suggested java:

if (attribute.nodeName.toLowerCase() == "name") {
var value = attribute.nodeValue.replace("[0]", "["+parseInt(counterField.value+1)+"]");
} else {
var value = attribute.nodeValue + idSuffix;
}

one " was missing in the second line of code -- "[" not, ["