@@ -11,10 +11,12 @@ import classNames from 'classnames';
1111import { FormElementProps } from '../../util/types/FormTypes' ;
1212import { generateRandomName } from '../../util/RandomName' ;
1313import LabelBlock from '../../util/LabelBlock' ;
14+ import FormContext , { IFormContext } from '../form/FormContext' ;
1415
1516interface IDateInputContext {
1617 isDateInput : boolean ;
1718 registerRef : ( type : DateInputType , ref : HTMLInputElement | null ) => void ;
19+ registerError : ( type : DateInputType , error : boolean | undefined ) => void ;
1820 name : string ;
1921 autoCompletePrefix : string | undefined ;
2022 error ?: string | boolean ;
@@ -23,6 +25,7 @@ interface IDateInputContext {
2325const DateInputContext = createContext < IDateInputContext > ( {
2426 isDateInput : false ,
2527 registerRef : ( ) => undefined ,
28+ registerError : ( ) => undefined ,
2629 name : '' ,
2730 autoCompletePrefix : '' ,
2831 error : '' ,
@@ -41,7 +44,7 @@ const DateInputInput: React.FC<DateInputInputProps> = ({
4144 autoComplete,
4245 ...rest
4346} ) => {
44- const { isDateInput, registerRef, name, autoCompletePrefix, error } = useContext <
47+ const { isDateInput, registerRef, name, autoCompletePrefix, registerError , error } = useContext <
4548 IDateInputContext
4649 > ( DateInputContext ) ;
4750 const inputRef = useRef < HTMLInputElement > ( null ) ;
@@ -52,6 +55,12 @@ const DateInputInput: React.FC<DateInputInputProps> = ({
5255 }
5356 } , [ inputRef . current ] ) ;
5457
58+ useEffect ( ( ) => {
59+ if ( isDateInput ) {
60+ registerError ( dateInputType , rest . error ) ;
61+ }
62+ } , [ rest . error ] ) ;
63+
5564 return (
5665 < div className = "nhsuk-date-input__item" >
5766 < div className = "nhsuk-form-group" >
@@ -123,6 +132,12 @@ type DateInputValue = {
123132 year : string ;
124133} ;
125134
135+ type DateInputErrors = {
136+ day : boolean | undefined ;
137+ month : boolean | undefined ;
138+ year : boolean | undefined ;
139+ } ;
140+
126141interface DateInputProps
127142 extends Omit < HTMLProps < HTMLDivElement > , 'onChange' | 'value' | 'defaultValue' > ,
128143 FormElementProps {
@@ -133,11 +148,16 @@ interface DateInputProps
133148 defaultValue ?: DateInputValue ;
134149}
135150
136- type DateInputState = {
151+ export type DateInputState = {
137152 name : string ;
138153 value : DateInputValue ;
154+ errors : DateInputErrors ;
139155} ;
140156
157+ interface DateInput extends PureComponent < DateInputProps , DateInputState > {
158+ context : IFormContext ;
159+ }
160+
141161interface DateInput extends PureComponent < DateInputProps , DateInputState > {
142162 monthRef : HTMLInputElement | null ;
143163 yearRef : HTMLInputElement | null ;
@@ -149,11 +169,33 @@ class DateInput extends PureComponent<DateInputProps, DateInputState> {
149169 this . state = {
150170 name : props . name || generateRandomName ( 'dateinput' ) ,
151171 value : { day : '' , month : '' , year : '' } ,
172+ errors : { day : undefined , month : undefined , year : undefined } ,
152173 } ;
153174 this . monthRef = null ;
154175 this . yearRef = null ;
155176 }
156177
178+ componentDidUpdate ( ) {
179+ if ( ! this . context . isForm ) return ;
180+ if ( this . props . error !== undefined ) {
181+ this . context . setError ( this . state . name , Boolean ( this . props . error ) ) ;
182+ } else {
183+ const { day, month, year } = this . state . errors ;
184+ const errorInChild = day || month || year ;
185+ this . context . setError ( this . state . name , Boolean ( errorInChild ) ) ;
186+ }
187+ }
188+
189+ registerError = ( type : DateInputType , error : boolean | undefined ) => {
190+ this . setState ( state => ( {
191+ ...state ,
192+ errors : {
193+ ...state . errors ,
194+ [ type ] : error ,
195+ } ,
196+ } ) ) ;
197+ } ;
198+
157199 registerRef = ( type : DateInputType , ref : HTMLInputElement | null ) => {
158200 if ( ref !== null ) {
159201 if ( type === 'Month' ) {
@@ -166,7 +208,6 @@ class DateInput extends PureComponent<DateInputProps, DateInputState> {
166208
167209 onChange = ( e : SyntheticEvent < HTMLInputElement > ) => {
168210 e . stopPropagation ( ) ;
169-
170211 const target = e . target as HTMLInputElement ;
171212 const { value, name } = this . state ;
172213 if ( target && target . name ) {
@@ -188,6 +229,7 @@ class DateInput extends PureComponent<DateInputProps, DateInputState> {
188229 currentTarget : { ...target , name, value } ,
189230 } ;
190231
232+ this . setState ( { value } ) ;
191233 if ( this . props . onChange ) {
192234 this . props . onChange ( newEvent ) ;
193235 }
@@ -202,6 +244,8 @@ class DateInput extends PureComponent<DateInputProps, DateInputState> {
202244 }
203245 } ;
204246
247+ static contextType = FormContext ;
248+
205249 static Day = DateInputDay ;
206250
207251 static Month = DateInputMonth ;
@@ -227,8 +271,10 @@ class DateInput extends PureComponent<DateInputProps, DateInputState> {
227271 ...rest
228272 } = this . props ;
229273 const { name } = this . state ;
274+
230275 const contextValue = {
231276 isDateInput : true ,
277+ registerError : this . registerError ,
232278 registerRef : this . registerRef ,
233279 name,
234280 autoCompletePrefix,
0 commit comments