Apologies if this shouldn't be considered webform specific, but I figured it made more sense here.

I have a client request to auto save drafts and remove the save draft button. I am tantalizingly close, but I'm hoping somebody can help me figure out what I'm missing. My approach is to use AJAX on each form component so that when losing focus a draft is saved. I have this working for the first component, but the save draft does not fire anymore after the first time. Can anybody see something obvious that I am missing?

Code for my module below:

function webform_autodraft_form_alter(&$form, &$form_state, $form_id) {
  // restrict to the test form
  if(strstr($form_id, 'webform_client_form_158')) {
    // get the nid so we can use it in the wrapper value
    $nid = $form['#node']->nid;
    
    foreach($form['submitted'] as $k => $c) {
      $form['submitted'][$k]['#ajax'] = array(
        'callback' => 'webform_autodraft_webform_js_draft',
        'wrapper' => 'webform-client-form-' . $nid,
        'method' => 'Replace',
        'effect' => 'fade',
      );
    }
  }
}

function webform_autodraft_webform_js_draft($form, &$form_state) {
  // check for existing submission
  global $user;
  $n = node_load($form_state['values']['details']['nid']);
  $draft_sid = _webform_fetch_draft_sid($n->nid, $user->uid);
  $form_state['values']['details']['sid'] = $draft_sid;
  
  // for some reason the form_state has the form_key not the cid. this function wants cid, so convert them over.
  $submitted = $form_state['values']['submitted'];
  foreach ($submitted as $k => $v) {
    // add new key
    $newkey = $form_state['complete form']['submitted'][$k]['#webform_component']['cid'];
    $form_state['values']['submitted'][$newkey] = $v;
    
    // kill old key
    unset($form_state['values']['submitted'][$k]);
  }
  unset($submitted);
  
  // draft to true then save!
  $form_state['save_draft'] = TRUE;
  webform_client_form_submit($form, $form_state);
//  drupal_set_message('<pre>Sid after:' . print_r($sid, true) . '</pre>');
  return $form;
}

Comments

quicksketch’s picture

Status: Active » Closed (won't fix)

As mentioned in the submission guidelines, I don't provide help with custom coding:

Any issues regarding "how do I code ..." or "how do I theme ..." will not be answered. Please look elsewhere for coding resources.

Please refer to other resources such as IRC or Drupal StackExchange to ask your questions.

petednz’s picture

Dear Uncle Justin

Did you ever get closer than 'tantalizingly close'?

unclejustin’s picture

Sadly, no. I eventually had to abandon this idea.

petednz’s picture

Thanks for the prompt response. I understand that type of 'tantalising' ;-)

Stefan Vaduva’s picture

Hello,

Starting from the code posted by unclejustin, I've managed to make it work with this callback for the ajax request:

function _my_module_js_draft($form, &$form_state) {
  global $user;
  $draft_sid = _webform_fetch_draft_sid($form['#node']->nid, $user->uid);

  $form_state['values']['details']['sid'] = $draft_sid;
  $form_state['values']['op'] = !empty($form['actions']['draft']['#value']) ? $form['actions']['draft']['#value'] : t('Save Draft');

  $form_state['save_draft'] = TRUE;
  webform_client_form_pages($form, $form_state);
  webform_client_form_submit($form, $form_state);

  return $form;
}

mbrowd’s picture

Hi Stefan,
How would you implement your code on the site? I made a custom module but nothing seems to be happening.
Thanks

Liam Morland’s picture

Version: 7.x-3.9 » 7.x-4.x-dev
Category: Support request » Feature request
Status: Closed (won't fix) » Active

This would be a valuable feature.

quicksketch’s picture

Hey Liam, this would be neat but probably incredibly difficult. Things get messy when dealing with file uploads and multiple pages. I'd probably prefer to see this implemented as a 3rd party module (at least initially). It depends on the complexity of the implementation whether we'd see this in the main project or not.

Liam Morland’s picture

For file uploads, I would just not handle them and instead have files uploaded when the page is submitted.

For multiple pages, this doesn't really increase the complexity. The Previous and Next buttons would function as before.

All I am suggesting is that when a form component changes, that component's value should be saved via Ajax. Saving a draft when changing pages is already implemented, so this isn't breaking any new ground in that regard.

I won't be working on this today, but I might give it a go sometime.

DanChadwick’s picture

Status: Active » Closed (won't fix)

I don't see this happening in webform core. Currently forms that fail validation can be saved as drafts. If you combine that with an onunload handler to save changes prior to leaving page, I think that's as close as we should come. I think that perhaps the feature to save each changed component could be done by an add-on module.

upperholme’s picture

Did this ever get any further? Is a module available?

swhitters’s picture

Can someone please take another look at this?

I wasn't completely sure this isn't a separate issue (and if it is I would be happy to open a new issue, as this one seems dead), but need to be able to autosave anonymous user responses as a draft on a multipage form after "next page" is clicked. It doesn't have to be an AJAX solution--I'd take some other module if it is available as well.

Thanks.

Liam Morland’s picture

This issue is about Ajax saving. Draft are already saved when switching pages for authenticated users.

swhitters’s picture

Oh, I didn't see it say authenticated. What about non-authenticated (anonymous) users? That's the problem. Should I start a new issue? I didn't want to duplicate.

Liam Morland’s picture

It would probably get done as part of #1932560: “Save draft” form button for anonymous users.