From bf142eb6ef39e34fad6bd459b96922ffe2a8533c Mon Sep 17 00:00:00 2001 From: Robbie Averill Date: Mon, 25 Mar 2019 15:09:38 +1300 Subject: [PATCH] FIX Display rules for page breaks/editable form steps now works again This was previously broken in a regression from https://github.com/silverstripe/silverstripe-userforms/pull/575 where the fields themselves could still be toggled, but the jQuery event dispatches for the form steps were removed. This pull request re-introduces those jQuery event triggers when hiding and showing editable form fields via display rules. --- code/Control/UserDefinedFormController.php | 7 ++++ code/Model/EditableCustomRule.php | 37 ++++++++++++++++++---- code/Model/EditableFormField.php | 11 +++++-- tests/Model/EditableCustomRuleTest.php | 13 ++++++++ 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/code/Control/UserDefinedFormController.php b/code/Control/UserDefinedFormController.php index d4001ed..b5576e0 100644 --- a/code/Control/UserDefinedFormController.php +++ b/code/Control/UserDefinedFormController.php @@ -17,6 +17,7 @@ use SilverStripe\ORM\FieldType\DBField; use SilverStripe\ORM\ValidationException; use SilverStripe\Security\Security; use SilverStripe\UserForms\Form\UserForm; +use SilverStripe\UserForms\Model\EditableFormField; use SilverStripe\UserForms\Model\EditableFormField\EditableFileField; use SilverStripe\UserForms\Model\Submission\SubmittedForm; use SilverStripe\View\ArrayData; @@ -166,6 +167,9 @@ class UserDefinedFormController extends PageController { $rules = ''; $form = $this->data(); + if (!$form) { + return; + } $formFields = $form->Fields(); $watch = []; @@ -499,6 +503,7 @@ JS $conjunction = $rule['conjunction']; $operations = implode(" {$conjunction} ", $rule['operations']); $target = $rule['targetFieldID']; + $holder = $rule['holder']; $result .= <<ConditionOption == 'IsNotBlank') { + if ((string) $this->ConditionOption === 'IsNotBlank') { //Negate $expression = "!({$expression})"; } @@ -200,7 +201,7 @@ class EditableCustomRule extends DataObject $expression = sprintf('%s.val() == "%s"', $target, $fieldValue); } - if ($this->ConditionOption == 'ValueNot') { + if ((string) $this->ConditionOption === 'ValueNot') { //Negate $expression = "!({$expression})"; } @@ -233,11 +234,33 @@ class EditableCustomRule extends DataObject * Returns the opposite visibility function for the value of the initial visibility field, e.g. show/hide. This * will toggle the "hide" class either way, which is handled by CSS. * - * @param string $text + * @param string $initialState + * @param boolean $invert * @return string */ - public function toggleDisplayText($text) + public function toggleDisplayText($initialState, $invert = false) { - return (strtolower($text) === 'hide') ? 'removeClass("hide")' : 'addClass("hide")'; + $action = strtolower($initialState) === 'hide' ? 'removeClass' : 'addClass'; + if ($invert) { + $action = $action === 'removeClass' ? 'addClass' : 'removeClass'; + } + return sprintf('%s("hide")', $action); + } + + /** + * Returns an event name to be dispatched when the field is changed. Matches up with the visibility classes + * added or removed in `toggleDisplayText()`. + * + * @param string $initialState + * @param bool $invert + * @return string + */ + public function toggleDisplayEvent($initialState, $invert = false) + { + $action = strtolower($initialState) === 'hide' ? 'show' : 'hide'; + if ($invert) { + $action = $action === 'hide' ? 'show' : 'hide'; + } + return sprintf('userform.field.%s', $action); } } diff --git a/code/Model/EditableFormField.php b/code/Model/EditableFormField.php index efa631b..f65e792 100755 --- a/code/Model/EditableFormField.php +++ b/code/Model/EditableFormField.php @@ -24,10 +24,12 @@ use SilverStripe\Forms\SegmentField; use SilverStripe\Forms\TabSet; use SilverStripe\Forms\TextField; use SilverStripe\ORM\ArrayList; +use SilverStripe\ORM\DataList; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DB; use SilverStripe\ORM\FieldType\DBField; use SilverStripe\ORM\FieldType\DBVarchar; +use SilverStripe\ORM\SS_List; use SilverStripe\ORM\ValidationException; use SilverStripe\UserForms\Extension\UserFormFieldEditorExtension; use SilverStripe\UserForms\Model\EditableFormField\EditableFieldGroup; @@ -965,9 +967,10 @@ class EditableFormField extends DataObject /** @var EditableFormField $formFieldWatch */ $formFieldWatch = DataObject::get_by_id(EditableFormField::class, $rule->ConditionFieldID); // Skip deleted fields - if (! $formFieldWatch) { + if (!$formFieldWatch) { continue; } + $fieldToWatch = $formFieldWatch->getSelectorFieldOnly(); $expression = $rule->buildExpression(); @@ -980,9 +983,11 @@ class EditableFormField extends DataObject $result['operations'][] = $expression['operation']; // View/Show should read - $opposite = ($result['initialState'] === 'hide') ? 'show' : 'hide'; $result['view'] = $rule->toggleDisplayText($result['initialState']); - $result['opposite'] = $rule->toggleDisplayText($opposite); + $result['opposite'] = $rule->toggleDisplayText($result['initialState'], true); + $result['holder'] = $this->getSelectorHolder(); + $result['holder_event'] = $rule->toggleDisplayEvent($result['initialState']); + $result['holder_event_opposite'] = $rule->toggleDisplayEvent($result['initialState'], true); } return (count($result['selectors'])) ? $result : null; diff --git a/tests/Model/EditableCustomRuleTest.php b/tests/Model/EditableCustomRuleTest.php index adc5116..3d08d9a 100644 --- a/tests/Model/EditableCustomRuleTest.php +++ b/tests/Model/EditableCustomRuleTest.php @@ -43,8 +43,21 @@ class EditableCustomRuleTest extends SapphireTest */ public function testToggleDisplayText() { + /** @var EditableCustomRule $rule1 */ $rule1 = $this->objFromFixture(EditableCustomRule::class, 'rule1'); $this->assertSame('addClass("hide")', $rule1->toggleDisplayText('show')); $this->assertSame('removeClass("hide")', $rule1->toggleDisplayText('hide')); + $this->assertSame('removeClass("hide")', $rule1->toggleDisplayText('show', true)); + $this->assertSame('addClass("hide")', $rule1->toggleDisplayText('hide', true)); + } + + public function testToggleDisplayEvent() + { + /** @var EditableCustomRule $rule1 */ + $rule1 = $this->objFromFixture(EditableCustomRule::class, 'rule1'); + $this->assertSame('userform.field.hide', $rule1->toggleDisplayEvent('show')); + $this->assertSame('userform.field.show', $rule1->toggleDisplayEvent('hide')); + $this->assertSame('userform.field.show', $rule1->toggleDisplayEvent('show', true)); + $this->assertSame('userform.field.hide', $rule1->toggleDisplayEvent('hide', true)); } }