Restricting Date Inputs
Background
In my day job I work for a software company building a clinical management system for the Aged Card sector. The system is a Rails & ReactJS application with some 3 million lines of code, so it is not a small application by any means.
The Problem The issue we have is that in one of the Registers, staff at various clients are entering dates manually and quite often incorrectly entering a future date in the field which throws the UI out by, in one instance 20,000 years. (Yep, someone entered a date of 16/12/22019!) The main BA on the project doesn’t like restricting user input and favours text boxes over select lists.
My frustration here comes from having to go into the DB on many systems and manually correct, or in some instances, delete, the offending records. Not my favourite thing to do! This leaves the facility in a fragile position whereby, someone outside of their organisation has altered their data. I hate doing it, but at this point, there is nothing they can do to fix the issue because archiving a record within the system would mean they have to find it first in a view that only shows 30 days at a time. A painfully long process, I can assure you.
On investigation, the reuseable component that we are using to render the date selector has a max date attribute set as ‘9999-12-31’! I will commend the optimism to have the system working for the next almost 8000 years, but really?! Here is what the component looks like:
<input
className="form-control"
disabled={disabled}
type="date" max="9999-12-31"
name={name}
value={this.state.date}
onChange = {(e) => {this.validateDateTime(e, "date")}}
style={{padding:"0 0 0 5px"}}
/>
Some Thoughts
Firstly, don’t ever assume that your users will always enter the right information every single time. I don’t say this because I think end users are stupid or anything like that. We all make mistakes and Nurses in Aged Care are super heroes for not only the work they do, but the stresses they deal with on a daily basis. Secondly, if you are of the same mindset as the BA, you need to ask why you don’t want to ensure the data going into your application is as clean as possible. Is it because it is easier to just not bother with data validation, or is it because you have an actual valid business reason that some date needs to be 20,000 years in the future?
In our case, I think it was the former. 🙁
The Solution The solution is simple. Validate everything! Like, seriously. Everything!
In our case, the max attribute in the date field is now this:
const {disabled, label, name, required, errorMessage, id, clearTime, dateOnly, maxDate = "9999-12-31"}{
~snip~
<input
className="form-control"
disabled={disabled}
type="date"
max={maxDate}
name={name}
value={this.state.date}
onChange = {(e) => {this.validateDateTime(e, "date")}}
style={{padding:"0 0 0 5px"}}
/>
~snip~
}
Now, that alone doesn’t fix the issue. Notice that the maxDate parameter is still set to that absurd date, this preserves the existing functionality so nothing breaks. So now we need to ensure that a date is passed to the maxDate parameter from the DateTimeField component like below:
<DateTimeField
id="entry_date"
name="entry_date"
value={this.props.data.entry_date}
label="Date shift started"
onChange = {this.onDateChange}
disabled={this.props.updateMode || canReadOnly}
required={true}
errorMessage='Please enter the Date shift started.'
clearTime={true} //clears the time when the date is cleared
dateOnly={true}
maxDate={moment(new Date()).format("YYYY-MM-DD")}
/>
And that is it! There is absolutely no way a user can now enter a date greater than today! If they attempt it, the field zeroes out that date part.
Conclusion
As per the screenshot below, you can no longer select a date after today. Winning!
Date Entry