diff --git a/classes/models/FrmFieldFormHtml.php b/classes/models/FrmFieldFormHtml.php
index 98634b3431..e9dc690408 100644
--- a/classes/models/FrmFieldFormHtml.php
+++ b/classes/models/FrmFieldFormHtml.php
@@ -526,6 +526,11 @@ private function add_multiple_input_attributes() {
$attributes['aria-required'] = 'true';
}
+ // Add 'aria-invalid' attribute to the group if there are errors.
+ if ( isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ) {
+ $attributes['aria-invalid'] = 'true';
+ }
+
// Concatenate attributes into a string, and replace the role="group" in the HTML with the attributes string.
$html_attributes = FrmAppHelper::array_to_html_params( $attributes );
$this->html = str_replace( ' role="group"', $html_attributes, $this->html );
diff --git a/classes/models/fields/FrmFieldCheckbox.php b/classes/models/fields/FrmFieldCheckbox.php
index 41bc9dc51f..7b1f2819ec 100644
--- a/classes/models/fields/FrmFieldCheckbox.php
+++ b/classes/models/fields/FrmFieldCheckbox.php
@@ -108,4 +108,17 @@ protected function show_readonly_hidden() {
protected function prepare_import_value( $value, $atts ) {
return $this->get_multi_opts_for_import( $value );
}
+
+ /**
+ * Unset aria-invalid for checkboxes because it's not valid for checkboxes.
+ * Instead aria-invalid is added to the checkbox group parent element.
+ *
+ * @since x.x
+ *
+ * @param array $shortcode_atts
+ * @param array $args
+ */
+ public function set_aria_invalid_error( &$shortcode_atts, $args ) {
+ unset( $shortcode_atts['aria-invalid'] );
+ }
}
diff --git a/classes/models/fields/FrmFieldRadio.php b/classes/models/fields/FrmFieldRadio.php
index b21d30f5d9..d8d62e57f6 100644
--- a/classes/models/fields/FrmFieldRadio.php
+++ b/classes/models/fields/FrmFieldRadio.php
@@ -109,4 +109,17 @@ protected function include_front_form_file() {
protected function show_readonly_hidden() {
return true;
}
+
+ /**
+ * Unset aria-invalid for radio buttons because it's not valid for radio buttons.
+ * Instead aria-invalid is added to the radiogroup parent element.
+ *
+ * @since x.x
+ *
+ * @param array $shortcode_atts
+ * @param array $args
+ */
+ public function set_aria_invalid_error( &$shortcode_atts, $args ) {
+ unset( $shortcode_atts['aria-invalid'] );
+ }
}
diff --git a/js/formidable.js b/js/formidable.js
index 451232fdf9..df085fc7eb 100644
--- a/js/formidable.js
+++ b/js/formidable.js
@@ -1147,7 +1147,12 @@ function frmFrontFormJS() {
input.attr( 'aria-describedby', describedBy );
}
- input.attr( 'aria-invalid', true );
+
+ if ( [ 'radio', 'checkbox' ].includes( input.attr( 'type' ) ) ) {
+ input.closest( '[role="radiogroup"], [role="group"]' ).attr( 'aria-invalid', true );
+ } else {
+ input.attr( 'aria-invalid', true );
+ }
jQuery( document ).trigger( 'frmAddFieldError', [ $fieldCont, key, jsErrors ] );
}
@@ -1186,8 +1191,13 @@ function frmFrontFormJS() {
fieldContainer.classList.remove( 'frm_blank_field', 'has-error' );
}
+ if ( 'true' === input.attr( 'aria-invalid' ) ) {
+ input.attr( 'aria-invalid', false );
+ } else if ( [ 'radio', 'checkbox' ].includes( input.attr( 'type' ) ) ) {
+ input.closest( '[role="radiogroup"], [role="group"]' ).attr( 'aria-invalid', false );
+ }
+
errorMessage.remove();
- input.attr( 'aria-invalid', false );
input.removeAttr( 'aria-describedby' );
if ( typeof describedBy !== 'undefined' ) {