From ffb516e5fb34e0e22934e95fcdc3d3f718e45c1d Mon Sep 17 00:00:00 2001 From: Guy Sartorelli Date: Fri, 15 Nov 2024 13:53:43 +1300 Subject: [PATCH] FIX Ensure schema data includes attributes --- src/Forms/FormField.php | 22 +++++++++++ src/Forms/SearchableDropdownTrait.php | 1 - src/Forms/TreeDropdownField.php | 2 - .../SilverStripe/Forms/TreeDropdownField.ss | 2 +- tests/php/Forms/FormFieldTest.php | 10 +++++ .../FormSchemaTest/testGetNestedSchema.json | 39 +++++++++++++++---- .../Forms/FormSchemaTest/testGetSchema.json | 6 ++- .../FormSchemaTest/testSchemaValidation.json | 37 +++++++++++++++--- 8 files changed, 102 insertions(+), 17 deletions(-) diff --git a/src/Forms/FormField.php b/src/Forms/FormField.php index d5a08e39a95..fe953afba8d 100644 --- a/src/Forms/FormField.php +++ b/src/Forms/FormField.php @@ -1493,6 +1493,16 @@ public function getSchemaDataDefaults() if ($titleTip instanceof Tip) { $data['titleTip'] = $titleTip->getTipSchema(); } + $attributes = $this->getAttributes(); + // Remove value from attributes because otherwise it breaks react fields + unset($attributes['value']); + // Remove above attributes from attributes list to avoid double-ups + foreach (array_keys($data) as $key) { + // HTML attributes are always lowercase so we need to make sure to transform our js key names + // to lowercase before unsetting them. + unset($attributes[strtolower($key)]); + } + $data['attributes'] = $attributes; return $data; } @@ -1562,6 +1572,18 @@ public function getSchemaValidation() return $validationList; } + /** + * Gets the data-schema and data-state attributes for the input element. + * Can't be included in getAttributesHtml because that would result in + * an infinite loop. + */ + public function getSchemaAttributesHtml(): DBHTMLText + { + $content = 'data-schema="' . htmlspecialchars(json_encode($this->getSchemaData())) + . '" data-state="' . htmlspecialchars(json_encode($this->getSchemaState())) . '"'; + return DBHTMLText::create()->setValue($content); + } + /** * @return Tip */ diff --git a/src/Forms/SearchableDropdownTrait.php b/src/Forms/SearchableDropdownTrait.php index fa751c49a2f..56e80821c62 100644 --- a/src/Forms/SearchableDropdownTrait.php +++ b/src/Forms/SearchableDropdownTrait.php @@ -312,7 +312,6 @@ public function getAttributes(): array parent::getAttributes(), [ 'name' => $name, - 'data-schema' => json_encode($this->getSchemaData()), ] ); } diff --git a/src/Forms/TreeDropdownField.php b/src/Forms/TreeDropdownField.php index 5bf454f5513..7a8889dafca 100644 --- a/src/Forms/TreeDropdownField.php +++ b/src/Forms/TreeDropdownField.php @@ -620,8 +620,6 @@ public function getAttributes() $attributes = [ 'class' => $this->extraClass(), 'id' => $this->ID(), - 'data-schema' => json_encode($this->getSchemaData()), - 'data-state' => json_encode($this->getSchemaState()), ]; $attributes = array_merge($attributes, $this->attributes); diff --git a/templates/SilverStripe/Forms/TreeDropdownField.ss b/templates/SilverStripe/Forms/TreeDropdownField.ss index fad2a4e5f3c..c17e1582d2b 100644 --- a/templates/SilverStripe/Forms/TreeDropdownField.ss +++ b/templates/SilverStripe/Forms/TreeDropdownField.ss @@ -1,6 +1,6 @@
data-metadata="$Metadata.ATT"<% end_if %> > diff --git a/tests/php/Forms/FormFieldTest.php b/tests/php/Forms/FormFieldTest.php index 7c75ddb3162..5c54010b005 100644 --- a/tests/php/Forms/FormFieldTest.php +++ b/tests/php/Forms/FormFieldTest.php @@ -414,6 +414,16 @@ public function testGetSchemaDataDefaultsTitleTip() $this->assertSame('Test tip', $schema['titleTip']['content']); } + public function testGetSchemaDataDefaultsAttributes() + { + $field = new FormField('MyField'); + $field->setAttribute('foo', 'bar'); + $this->assertEquals('bar', $field->getAttribute('foo')); + $schema = $field->getSchemaDataDefaults(); + $this->assertArrayHasKey('foo', $schema['attributes']); + $this->assertEquals('bar', $schema['attributes']['foo']); + } + public function testGetSchemaData() { $field = new FormField('MyField'); diff --git a/tests/php/Forms/FormSchemaTest/testGetNestedSchema.json b/tests/php/Forms/FormSchemaTest/testGetNestedSchema.json index 8386f140c0b..0c0ab36bae6 100644 --- a/tests/php/Forms/FormSchemaTest/testGetNestedSchema.json +++ b/tests/php/Forms/FormSchemaTest/testGetNestedSchema.json @@ -30,7 +30,11 @@ "disabled": false, "autoFocus": false, "customValidationMessage": "", - "attributes": [], + "attributes": { + "class": "text", + "readonly": false, + "autofocus": false + }, "data": { "maxlength": null }, @@ -53,7 +57,11 @@ "disabled": false, "autoFocus": false, "customValidationMessage": "", - "attributes": [], + "attributes": { + "class": "hidden", + "readonly": false, + "autofocus": false + }, "data": [], "validation": [] } @@ -77,7 +85,10 @@ "autoFocus": false, "customValidationMessage": "", "attributes": { - "type": "submit" + "type": "submit", + "class": "action", + "readonly": false, + "autofocus": false }, "data": { "icon": "save" @@ -102,7 +113,10 @@ "autoFocus": false, "customValidationMessage": "", "attributes": { - "type": "button" + "type": "button", + "class": "action", + "readonly": false, + "autofocus": false }, "data": { "icon": null @@ -126,7 +140,12 @@ "disabled": false, "autoFocus": false, "customValidationMessage": "", - "attributes": [], + "attributes": { + "class": "field CompositeField popover", + "readonly": null, + "autofocus": false, + "tabindex": null + }, "data": { "popoverTitle": null, "placement": "bottom", @@ -159,7 +178,10 @@ "autoFocus": false, "customValidationMessage": "", "attributes": { - "type": "submit" + "type": "submit", + "class": "action", + "readonly": false, + "autofocus": false }, "data": { "icon": null @@ -184,7 +206,10 @@ "autoFocus": false, "customValidationMessage": "", "attributes": { - "type": "submit" + "type": "submit", + "class": "action", + "readonly": false, + "autofocus": false }, "data": { "icon": null diff --git a/tests/php/Forms/FormSchemaTest/testGetSchema.json b/tests/php/Forms/FormSchemaTest/testGetSchema.json index 57a2ef642bf..387e8ce857c 100644 --- a/tests/php/Forms/FormSchemaTest/testGetSchema.json +++ b/tests/php/Forms/FormSchemaTest/testGetSchema.json @@ -30,7 +30,11 @@ "disabled": false, "autoFocus": false, "customValidationMessage": "", - "attributes": [], + "attributes": { + "class": "hidden", + "readonly": false, + "autofocus": false + }, "data": [], "validation": [] } diff --git a/tests/php/Forms/FormSchemaTest/testSchemaValidation.json b/tests/php/Forms/FormSchemaTest/testSchemaValidation.json index e7f3bc3d0b0..fed43705358 100644 --- a/tests/php/Forms/FormSchemaTest/testSchemaValidation.json +++ b/tests/php/Forms/FormSchemaTest/testSchemaValidation.json @@ -36,7 +36,15 @@ "length": 40 } }, - "attributes": [], + "attributes": { + "class": "text", + "readonly": false, + "autofocus": false, + "required": "required", + "aria-required": "true", + "maxLength": 40, + "size": 30 + }, "data": { "maxlength": 40 } @@ -62,7 +70,14 @@ "validation": { "date": true }, - "attributes": [], + "attributes": { + "class": "date text", + "readonly": false, + "autofocus": false, + "lang": "en-US", + "min": null, + "max": null + }, "data": { "html5": true, "min": null, @@ -90,7 +105,11 @@ "validation": { "numeric": true }, - "attributes": [], + "attributes": { + "class": "numeric text", + "readonly": false, + "autofocus": false + }, "data": { "maxlength": null } @@ -115,7 +134,11 @@ "validation": { "currency": true }, - "attributes": [], + "attributes": { + "class": "currency text", + "readonly": false, + "autofocus": false + }, "data": { "maxlength": null } @@ -138,7 +161,11 @@ "autoFocus": false, "customValidationMessage": "", "validation": [], - "attributes": [], + "attributes": { + "class": "hidden", + "readonly": false, + "autofocus": false + }, "data": [] } ],