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 .= <<<EOS
 \n
@@ -507,8 +512,10 @@ JS
     function (){
         if ({$operations}) {
             $('{$target}').{$rule['view']};
+            {$holder}.{$rule['view']}.trigger('{$rule['holder_event']}');
         } else {
             $('{$target}').{$rule['opposite']};
+            {$holder}.{$rule['opposite']}.trigger('{$rule['holder_event_opposite']}');
         }
     });
     $("{$target}").find('.hide').removeClass('hide');
diff --git a/code/Model/EditableCustomRule.php b/code/Model/EditableCustomRule.php
index 59cbd8b..e3951bf 100644
--- a/code/Model/EditableCustomRule.php
+++ b/code/Model/EditableCustomRule.php
@@ -7,14 +7,15 @@ use SilverStripe\CMS\Controllers\CMSMain;
 use SilverStripe\Control\Controller;
 use SilverStripe\Core\Convert;
 use SilverStripe\ORM\DataObject;
-use Silverstripe\Versioned\Versioned;
+use SilverStripe\Security\Member;
+use SilverStripe\Versioned\Versioned;
 
 /**
  * A custom rule for showing / hiding an EditableFormField
  * based the value of another EditableFormField.
  *
  * @method EditableFormField Parent()
- * @package userforms
+ * @method EditableFormField ConditionField()
  *
  * @property string Display
  * @property string ConditionOption
@@ -172,7 +173,7 @@ class EditableCustomRule extends DataObject
             case 'IsNotBlank':
             case 'IsBlank':
                 $expression = ($checkboxField || $radioField) ? "!{$target}.is(\":checked\")" : "{$target}.val() == ''";
-                if ($this->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));
     }
 }