From d406d973823d91d05078f8c658801b7b72f1db66 Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Wed, 1 Dec 2021 00:20:42 -0500 Subject: [PATCH] Feature: Support Multi-Step Paged Forms Adds ability to have multiple submit buttons/inputs. With this change (and a specific method of setup in the form templates), form data can be posted when navigating away from the current form step. --- .../formalicioussnippetrenderform.class.php | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/core/components/formalicious/model/formalicious/snippets/formalicioussnippetrenderform.class.php b/core/components/formalicious/model/formalicious/snippets/formalicioussnippetrenderform.class.php index efc293d..2f208fa 100644 --- a/core/components/formalicious/model/formalicious/snippets/formalicioussnippetrenderform.class.php +++ b/core/components/formalicious/model/formalicious/snippets/formalicioussnippetrenderform.class.php @@ -147,7 +147,7 @@ public function run(array $properties = []) $hooks[] = 'FormaliciousHookHandleForm'; } - if ($currentStep >= $totalSteps) { + if ($currentStep >= $totalSteps && isset($_POST[$parameters['submitVar']])) { if (!in_array('FormaliciousHookRemoveForm', $hooks, true)) { $hooks[] = 'FormaliciousHookRemoveForm'; } @@ -198,8 +198,30 @@ public function run(array $properties = []) } else { $hooks[] = 'redirect'; + /* + Set up redirect in a way that allows variable/dynamic destination, based on + value stored in the submit input/button. This way, form data on the step that is + being navigated away from will always be posted/saved. Navigation and pagination + should then be done via submit inputs/buttons instead of tags. + + A related change to FormIt's Request class is necessary for this additional functionality. + */ + + # Default redirect destination + $destination = $currentStep + 1; + + # Check for alternate destination request + if ($_POST) { + foreach ($_POST as $k => $v) { + if (strpos($k, $parameters['submitVar']) !== false) { + $destination = is_numeric($v) ? $v : $destination ; + break; + } + } + } + $parameters['redirectTo'] = $this->getStepUrl([ - $this->getProperty('stepParam') => $currentStep + 1 + $this->getProperty('stepParam') => (int)$destination ], 'full'); if (empty($placeholders['submitTitle'])) { @@ -226,21 +248,23 @@ public function run(array $properties = []) $parameters['formaliciousTplNavigationItem'] = $this->getProperty('tplNavigationItem'); $parameters['formaliciousTplNavigationWrapper'] = $this->getProperty('tplNavigationWrapper'); - if ($currentStep <= 1) { - $placeholders['prevUrl'] = $this->getStepUrl(); - } else { + if ($currentStep > 1) { $placeholders['prevUrl'] = $this->getStepUrl([ $this->getProperty('stepParam') => $currentStep - 1 ]); + $placeholders['submitValPrev'] = $currentStep - 1; } - if ($totalSteps === 1) { - $placeholders['currentUrl'] = $this->getStepUrl(); - } else { - $placeholders['currentUrl'] = $this->getStepUrl([ - $this->getProperty('stepParam') => $currentStep - ]); - } + $placeholders['submitValLast'] = $totalSteps; + + # Suggest renaming this placeholder, as it makes its purpose more immediately clear + $placeholders['formAction'] = $totalSteps === 1 + ? $this->getStepUrl() + : $this->getStepUrl([$this->getProperty('stepParam') => $currentStep]) + ; + + # Set orignal for backward compatibility + $placeholders['currentUrl'] = $placeholders['formAction']; return $this->getChunk($this->getProperty('tplForm'), array_merge($placeholders, $parameters, [ 'FormItParameters' => $this->parseParameters($parameters),