diff --git a/packages/eui/changelogs/upcoming/8952.md b/packages/eui/changelogs/upcoming/8952.md
new file mode 100644
index 00000000000..00ab971c121
--- /dev/null
+++ b/packages/eui/changelogs/upcoming/8952.md
@@ -0,0 +1,3 @@
+**Bug fixes**
+
+- Fixed an issue where the validity state of `EuiFieldNumber` did not update when the `isInvalid` prop value changed
diff --git a/packages/eui/src/components/form/field_number/field_number.spec.tsx b/packages/eui/src/components/form/field_number/field_number.spec.tsx
index 30ab1b40dd5..cd7ecff0c32 100644
--- a/packages/eui/src/components/form/field_number/field_number.spec.tsx
+++ b/packages/eui/src/components/form/field_number/field_number.spec.tsx
@@ -10,19 +10,35 @@
///
///
-import React, { useState } from 'react';
+import React, { ChangeEventHandler, useState } from 'react';
+import { EuiForm } from '../form';
+import { EuiFormRow } from '../form_row';
import { EuiFieldNumber } from './field_number';
+import { EuiText } from '../../text';
describe('EuiFieldNumber', () => {
describe('isNativelyInvalid', () => {
- const checkIsValid = () => {
- cy.get('[aria-invalid="true"]').should('not.exist');
- cy.get('.euiFormControlLayoutIcons').should('not.exist');
+ const checkIsValid = (selector = 'input') => {
+ cy.get(selector)
+ .then(($el) => ($el[0] as HTMLInputElement).checkValidity())
+ .should('be.true');
+ cy.get(selector).should('not.have.attr', 'aria-invalid', 'true');
+ cy.get(selector)
+ .parent()
+ .find('.euiFormControlLayoutIcons')
+ .should('not.exist');
};
- const checkIsInvalid = () => {
- cy.get('[aria-invalid="true"]').should('exist');
- cy.get('.euiFormControlLayoutIcons').should('exist');
+
+ const checkIsInvalid = (selector = 'input') => {
+ cy.get(selector)
+ .then(($el) => ($el[0] as HTMLInputElement).checkValidity())
+ .should('be.false');
+ cy.get(selector).should('have.attr', 'aria-invalid', 'true');
+ cy.get(selector)
+ .parent()
+ .find('.euiFormControlLayoutIcons')
+ .should('exist');
};
it('when the value is not a valid number', () => {
@@ -171,6 +187,75 @@ describe('EuiFieldNumber', () => {
cy.get('#setValidStep').click();
checkIsValid();
});
+
+ it('isInvalid', () => {
+ const FieldNumberValidationComponent = () => {
+ const [value1, setValue1] = useState('5');
+ const [value2, setValue2] = useState('4');
+
+ const onChange1: ChangeEventHandler = (e) => {
+ const newValue = e.target.value;
+ setValue1(newValue);
+ };
+
+ const onChange2: ChangeEventHandler = (e) => {
+ const newValue = e.target.value;
+ setValue2(newValue);
+ };
+
+ const isValue2GreaterThanValue1 = value2 > value1;
+
+ return (
+
+
+
+
+
+
+ <>
+
+ {isValue2GreaterThanValue1 && (
+
+ value2 should be smaller than value1
+
+ )}
+ >
+
+
+ );
+ };
+
+ const value1Selector = '[data-test-subj="value1"]';
+ const value2Selector = '[data-test-subj="value2"]';
+
+ cy.mount();
+ checkIsValid(value1Selector);
+ checkIsValid(value2Selector);
+
+ // Set `value2` to a value greater than `value1` (5 < 6) => invalid
+ cy.get(value2Selector).clear();
+ cy.get(value2Selector).focus().realType('6');
+ checkIsValid(value1Selector);
+ checkIsInvalid(value2Selector);
+
+ // Set `value1` to a value greater than `value2` (6 > 5) => valid
+ cy.get(value1Selector).clear();
+ cy.get(value1Selector).focus().realType('6');
+ checkIsValid(value1Selector);
+ checkIsValid(value2Selector);
+ });
});
});
});
diff --git a/packages/eui/src/components/form/field_number/field_number.tsx b/packages/eui/src/components/form/field_number/field_number.tsx
index 2e648b9cdee..28129bd1ae5 100644
--- a/packages/eui/src/components/form/field_number/field_number.tsx
+++ b/packages/eui/src/components/form/field_number/field_number.tsx
@@ -132,7 +132,7 @@ export const EuiFieldNumber: FunctionComponent = (
if (_inputRef.current) {
checkNativeValidity(_inputRef.current);
}
- }, [value, min, max, step, checkNativeValidity]);
+ }, [isInvalid, value, min, max, step, checkNativeValidity]);
const classes = classNames('euiFieldNumber', className, {
'euiFieldNumber-isLoading': isLoading,