5

How can I alter the key/value items of a checkboxes component in a webform?
I've followed this answer and I successfully altered a select list component for both render and submission.
I'm trying to do the same with a multiple choice component, but although the form is rendered correctly, the values are not saved on submission.
This is my code:

function my_form_webform_client_form_30_alter (&$form, &$form_state) {
    $form = mycustom_form($form);
}

function mycustom_form($form){  
     $form['#validate'][] = 'mycustom_webform_validate_form';
     $form['#submit'][] = 'mycustom_webform_submit';
     dpm($form['submitted']['code']['#options']); // ('0'=>'a value', '1'=>'another value');
     $codes = array('foo', 'bar'); 
     foreach ($codes as $key => $value) {
        $form['submitted']['code']['#options'][$value] = $value;
     } 

return $form;
}

function mycustom_webform_validate_form($form, &$form_state) {
dpm($form_state['values']['submitted']);
// selecting all checkboxes I get all the four values
}

function mycustom_webform_submit($form, &$form_state) {
  drupal_set_message('<pre>' . print_r($form_state, true) . '</pre>');
// only 'a value' and 'another value' are submitted
}

UPDATE
I even tried to add some values to the initial form and manipulate them programmatically.
The submission result is like no manipulation was done.
I update my code for a better explanation.

UPDATE 2
I've tried dumping the submitting form.
I updated my code with the results.

UPDATE 3
I confirm that removing the "Multiple" flag from the component, causes the issue to be fixed.
Unfortunately I need a multiple answer, so I can't remove it.

UPDATE 4
This is another solution I'm trying, using hook_webform_select_options_info():

function mycustom_webform_select_options_info() {
    $items = array();

   if (function_exists('_mycustom_users_options')) {
        $items['code'] = array(
        'title' => t('User codes'),
        'options callback' => '_mycustom_users_options',
      );
 }

  return $items;
}

function _mycustom_users_options() {
  $output = array();
  $codes = mycustom_user_codes(); // <- these values are based on logged user
  foreach ($codes as $key => $value) {
    $output[$value] = $value;
  }
  return $output;
}  

function mycustom_user_codes() {
      $result = // a db query based on user id;
      while($usercode = db_result($result)){
         $output[] = $usercode;
      }

      return $output; // array({[0] => 'a value', [1] =>'another value'})
}
  • I'm a bit confused by your code. Why are you calling mycustom_form() instead of just adding/editing the $form array you already have? Why do you have the same function mycustom_webform_validate_form () twice? Also, $form is passed by reference as a function argument in validate and submit handlers, i.e. _submit(&$form, &$form_state). Let me know, and if you've skipped some code please post it – I think I can help you figure this out. – Charlie Schliesser Jan 23 '13 at 23:45
  • The second validation was a copy/paste error. It should be mycustom_webform_submit. It's corrected now. I could edit the $form in the _alter function, but I need it in more than one _alter, so I created a separated function to do the job. Actually the problem is not about editing the form. The issue is related to submitting it. Checking the HTML created by my override, there's no difference between the two original values ('a value' and 'another value') and the two added ones ('foo' and 'bar'). But when I submit them, the altered values are not submitted. – pasine Jan 24 '13 at 8:46
  • Webform could be changing the options back to their original values in its submit or validate handler. Can you try unsetting the webform submit handler and just use yours, then do a dpm() or print_r() on $form_state to see if they're there? At least you'd know where the change is happening. – Charlie Schliesser Jan 24 '13 at 14:11
1

I've just tested the following code out locally and it "works", with the exception that when I view the submission results as an administrator, I see the original keys and not the keys that were altered when the form was displayed (which is what I would expect).

function my_custom_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'webform_client_form_12') { // yours is different
    // 'options' is the component name for a multiple-checkbox component.
    $form['submitted']['options']['#options'] = array(
      1 => 'Foo',
      2 => 'Bar',
    );

    $form['#submit'][] = 'my_custom_submit';
  }
}

function my_custom_submit(&$form, &$form_state) {
  dpm($form_state);
}

dmp($form_state) showed me that the checkbox I had picked was indeed the one that was checked, and when I look in the database in webform_submitted_data I can see that the record shows the proper value that I checked:

nid sid cid no data
12  12  2   0  2

where data = 2 shows the checkbox that I picked in my altered options (I picked "Bar").

Since the subsequent submission display is going to show the keys as they currently exist, it's showing me that I picked the original value for option #2. If I change that to "apples" in the component and then refresh the submission, it shows the 2nd option as "apples". So I could follow this up with another hook_webform_submission_render_alter() or hook_webform_submission_load() to change the options being displayed on submission view so as to be appropriate to who the user was that filled out the webform.

My suggestion would be to instead build your own form, since it sounds like you have more than one dynamic aspect for what you need, and store the data that will be dynamic as a serialized array in a 'data' column in your own table.

  • You are pointing me to an unexplored solution. This sounds really interesting. I am actually looking at the _webform_submit_select function that says "Convert FAPI 0/1 values into something saveable". I've tried to override it with a my_custom_webform_submit_select, but without success. Any clue? – pasine Jan 24 '13 at 17:23
  • _webform_submit_select() looks like it just exists so that keys (i.e. 0 /unchecked) are actually saved as something usable in the database. I think we're handling that already by doing 1 => 'foo', 2 => 'bar'. But if you wan to have dynamic elements per user and actually display the results that way, just build your own form, serialize the results, and store them. – Charlie Schliesser Jan 25 '13 at 15:48
  • I'm avoiding to create my own form, since i don't want to lose all the webform benefits. – pasine Jan 26 '13 at 13:43
0

Your $codes array is zero-based. This is usually bad, and can mess up the submitted values (especially if you check the 0-keyed option). Here's something from the Form API docs, for #checkboxes:

The #options array can not have a 0 key, as it would not be possible to discern checked and unchecked states.

This applies both to form generation (where you created the checkboxes for "a value" and "another value"), and to the form altering, submission etc. So a solution would be to manually specify the keys of your #options, like

$codes = array(
    "foo" => "foo",
    "bar" => "bar"
);

Or, if you want numerical,

$codes = array(
    1 => "foo",
    2 => "bar"
);

Just avoid the 0 key for checkboxes.

EDIT: I see that in hook_form_alter() you did, indeed, use foo and bar for keyes. Anyway, you have a 0 key when generating the checkboxes, so my observation stands, even if it might not fix the issue. I can't comment on your question (which would have been more appropriate for my observation), so I'll leave this "beware of 0-key" warning as an answer, to be visible.

0

Since webform3 there is hook_webform_select_options_info() for setting select ( or multiple choice ) options programatically.

I have been able to achieve this effectively in drupal 7 but there is a tutorial for drupal 6 and 7 here http://www.anexusit.com/blog/how-create-pre-built-list-webform-drupal-67

The tutorial that I followed to get me going on drupal 7 is here http://eureka.ykyuen.info/2012/04/11/drupal-7-dynamic-select-options-for-webform/ and gives more detail on how to setup the webform ( which should be very similar ).

This should prove to be a much cleaner way of achieving what you are looking to do rather than altering the form and attempting to hack it back into webform.

  • this is actually the solution I tried a couple of weeks ago, but since the keys/values are related to the logged user, they look different when I retrive the values from the backend. I add some code to explain what I mean. – pasine Jan 24 '13 at 13:56
  • Ok, can you please post the code for mycustom_user_codes() function? I also noticed that you have mycustom_fatture_webform_select_options_info() which should be mycustom_webform_select_options_info() but I am guessing that you have just copied that wrong. – James Jan 24 '13 at 14:14
-1

YOu need to pass $value by reference not by value, you should do it with &$value read more.

foreach ($codes as $key => &$value) {
              $form['submitted']['code']['#options'][$value] = $value;
            }
  • I've tried your suggestion but it doesn't work. $value is a local scope variable, so I don't understand how referencing can affect it. – pasine Dec 27 '12 at 16:58
  • I added some more code for a better explanation. – pasine Dec 27 '12 at 20:25
  • i dont know about d6 atm, cannot test anything, but dotn you need to do this -> function mycustom_form(&$form){ – Petro Popelyshko Dec 27 '12 at 20:29
  • No, the reference is just for the hook_form_alter. – pasine Dec 27 '12 at 20:41
-1
$codes = array('foo', 'bar'); 
foreach ($codes as $key => $value) {
  $form['submitted']['code']['#options'][$value] = $value;
}

could be written as:

$form['submitted']['code']['#options'] = array('foo', 'bar');
  • 1
    Thanks for your suggestion, but I'm not looking for refactoring tips, I'm looking for a solution to my problem. – pasine Jan 2 '13 at 15:35
  • 1
    The code also don't use the $value as a key. It could solve your problem. – Martin Poulsen Jan 2 '13 at 15:49
  • I already tried not using the $value as key, but this didn't solve the problem – pasine Jan 2 '13 at 16:12
  • While we're refactoring, $form['submitted']['code']['#options'] = drupal_map_assoc(array('foo', 'bar')); – Charlie Schliesser Jan 23 '13 at 23:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.