Hi,

I have a form that contains a "#action" element. When I write hook_validate() for this, it won't validate. It doesn't even hit the hook_validate() function that written for it. When I comment out the "#action" element in the form, the form validates when "submit" is clicked.

Here's the code:

function custom_paper_form(($form, &$form_state) {
  $form['#action'] = url('testpage');
  
	$form['tests_taken'] = array(
		'#type' => 'checkboxes',
		'#options' => drupal_map_assoc(array(t('SAT'), t('ACT'))),
		'#title' => t('What standardized tests did you take?'),
  ),

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );

  return $form;

}

function custom_paper_form_validate($form_id, &$form) {
  // Don't come here unless I remove the "#action" element from form
	drupal_set_message('Form validation');
}

function custom_paper_form_submit($form_id, &$form) {
  drupal_set_message(t('Submitted.'));
}

Now here is two solution comes to my mind :
1. I do remove '#action' from $form array and using drupal_goto() function redirect to action url say 'testpage' in my case. But in this case I need to pass $form values in query string that I don't want.
2. I restrict with '#action' attribute in $form and found any drupal function that do something here for me.

After some research I found there was one function in Drupal 6 for this i.e drupal_execute(); and in Drupal7 alternative function is drupal_form_submit(). but I am not getting example of such type where '#action' is given inside form.

Please help me to fix this issue.

Comments

Jaypan’s picture

Why are you wanting to change the #action on the form? It sounds like you may be doing things in a non-Drupally way, maybe we can point you at a way that will work better within the Drupal Form API.

er.pushpinderrana’s picture

Thanks Jaypan for quick reply.

Actually I want to auto populate this form values in another form where this form is redirecting. Actually $form['#action'] = url('testpage'); testpage contains another form where I need values of that form i.e custom_paper_form. And both forms are completely independent, so I can not use concept of mutistep form. Even this '#action' parameter can by dynamic in future. So I need post values of custom_paper_form on this action page.

It is always true that '#action' always contains internal node of drupal. So there is possibility of other good method that can fulfil my requirement, if you have please share with me.

Thanks

Pushpinder Rana #pushpinderdrupal
Acquia Certified Drupal Expert

Jaypan’s picture

Can you give an example of how you are (intending) to use the submitted values on the second form?

er.pushpinderrana’s picture

Thanks Jaypan.

I have created a sample example for you, also executed at my end. So there is less chance of TYPO mistake and you can directly check this.

First I created a form using custom block and assigned to one node. Given is the code.

function test1_form($form, &$form_state) {
	$form['#action'] = url('testpage');
  
  $form['name'] = array(
		'#title' => t('Name'),
		'#type' => 'textfield',
		'#description' => t('Enter Name.'),
	);
	
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );

  return $form;
}	

Then I created a node and make url alias of this node 'testpage' that given in '#action' of this form.

After this I again created a second form using custom block and assigned that form to this 'testpage' node.

function test2_form($form, &$form_state) {
	
	$form['name_value'] = array(
        '#type' => 'item',
        '#markup' => isset($_POST['name']) ? check_plain($_POST['name']) : '', // Get last form submitted value.
  );
	
	$form['name_value_hidden'] = array(
		'#type' => 'hidden', 
		'#value' =>	isset($_POST['name']) ? check_plain($_POST['name']) : '', 
	);
	
	$form['age'] = array(
			'#title' => t('Age'),
			'#type' => 'textfield',
			'#description' => t('Enter Age'),
	);
	
	$form['submit'] = array(
    '#type' => 'submit', 
		'#value' => t('Go')
  );
	
	return $form;
}

So on this second form i.e test2 form, I get last form value. This is just a sample example, I think this time I better described my problem.

Thanks

Pushpinder Rana #pushpinderdrupal
Acquia Certified Drupal Expert

Jaypan’s picture

I'm not sure there is an easy way to do it with POST values, but you can do it with GET values by doing the following:

function form_1($form, &$form_state)
{
  $form['element'] = array
  (
    '#type' => 'textfield',
    '#title' => t('Enter a value'),
  );
  $form['element_submit'] = array
  (
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  return $form;
}

function form_1_submit($form, &$form_state)
{
  $form_state['redirect'] = array('form_2', array('query' => array('element_value' => $form_state['values']['element_value'])));
}

function form_2($form, &$form_state)
{
  $form['some_element'] = array
  (
    '#type' => 'textfield',
    '#title' => t('Enter a value'),
    '#default_value' => isset($_GET['element_value']) ? check_plain($_GET['element_value']) : '',
  );
  return $form;
}

form_1() defines your first form. form_1_submit() is the submit function for that form, and redirects the user to the second form, passing a value in the URL. form_2() then uses the $_GET value to populate the form element in the second form.

er.pushpinderrana’s picture

Thanks Jaypan for your valuable opinion.

As I have mentioned in my post, I can't use GET method because I need to cached this page using Varnish. Varnish don't cache the URL(s) that contains query string (?) in URL. And there is some other limitation too, so I can't use GET method here.

I am working on this issue as I get any solution for this will share here.

Thanks

Pushpinder Rana #pushpinderdrupal
Acquia Certified Drupal Expert

Jaypan’s picture

Then you can do the following. First, you need to set up your form on a menu path:

function my_menu()
{
  $menu['form2'] = array
  (
    'title' => 'Form 2',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('form_2'), 
    'access callback' => TRUE;
  );
  return $form;
}

This will create your page for form 2. Then you can set up your redirect (from my original code) like this:

$form_state['redirect'] = 'form_2/' . $form_state['values']['element_value'];

This will pass the value as part of the path, rather than as a $_GET value. The value is then available in your form definition, in this case as $value_from_url.

function form_2($form, &$form_state, $value_from_url = FALSE)
{
  $form['some_element'] = array
  (
    '#type' => 'textfield',
    '#title' => t('Enter a value'),
    '#default_value' => $value_from_url ? check_plain($value_from_url) : '',
  );
  return $form;
}
er.pushpinderrana’s picture

Yes I agree with your solution. This can be a better way to solve my problem.

Thanks a lot JAYPAN.

Pushpinder Rana #pushpinderdrupal
Acquia Certified Drupal Expert