How to show next form after first one is validated?

Hi guys!

I need to store users requests only when users email is confirmed. This behavior is realized by two forms: first of them collects user info and message and second accepts confirmation code that was sent to user email by the first form processing. After the second form is validated users message emailed to recipient.

I have resource with shippet that publish forms and two FormIt calls for each form.

[[!ShowRequestForm]]

[[!FormIt ?
&submitVar=`presubmit`
&customValidators=`validateName`
&validate=`name:required:validateName,
email:email,
message:minLength=^8^`
]]

[[!FormIt ?
&hooks=`email,redirect`
&emailTo=`recipient email`
&emailFrom=`recipient email`
&emailSubject=`Subject`
&emailTpl=`SuccessMessage`
&redirectTo=`15`
&submitVar=`submitcode`
&customValidators=`validateAcceptCode`
&validate=`usercode:required:validateAcceptCode`
]]

Snippet ShowRequestForm:

// We have submitted first request form	
if (isset($_POST['presubmit']))
{
	
	// There is configuring confirmation code
	
	// Send email with confirmation code to user
	$modx->runSnippet('SendEmail', array(
		'to_addr' => $_POST['email'],
		'to_name' => $_POST['name'],
		'sender' => 'noreply address',
		'subject' => 'Confirmation code',
		'body' => $modx->getChunk('ConfirmationCodeBody', array(
			'code' => $confCode,
			'email' => $_POST['email'],))));

	// Publish next form to confirm code
	echo $modx->getChunk('AcceptCodeForm', array(
		'name' => $_POST['name'],
		'email' => $_POST['email'],
		'message' => $_POST['message'],));
}
else
{
	// We will accept only forms submits
	if (!isset($_POST['submitcode']))
		echo $modx->getChunk('MeetRequestForm');
	else
	// Second form has not passed validation
		echo $modx->getChunk('AcceptCodeForm', array(
			'name' => $_POST['name'],
			'email' => $_POST['email'],
			'message' => $_POST['message'],));
}

In result I couldn’t stop at validation failure for the first form. When it submitted I’m always stand on second form.

When I add snippet ShowRequestForm to hook of the first form, there is no changes happens.

What I do wrong? How to stop processing when the first form is not validated?

You probably want to use a custom hook, as it only executes after the form is validated.

But I think you will need to change your snippet code.
In the hook use $hook->getValue('email') instead of $_POST['email'], also I’m pretty sure you shouldn’t use echo. Maybe you can make it work with a placeholder:

Set a placeholder in the hook like: $modx->setPlaceholder('first_form_valid',1);
Then check the value in the template to output the chunk:

[[!+first_form_valid:is=`1`:then=`[[$AcceptCodeForm]]`]]

maybe it would be better to place the forms and formit - calls on two different resources and use formitretriever
https://docs.modx.com/current/en/extras/formit/formit.formitretriever

I had the same thought as bruno17.

Another thing to think about is doing your validation with JavaScript, which can then keep the form from being “submitted” unless it’s valid.

You might also look at the code of the Subscribe extra, which emails the user after a valid form is submitted with a link to a second page that asks about their preferences. It seems a lot like what you’re trying to do. In fact, Subscribe might work for your purposes with a little customization.