How to restrict past date selection in due date field in problem task
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hi Team,
I want to restrict past date selection in due date field in problem task and Change task tables.
I have tried directly in UI Policy, it is working but in form it is showing error, if selected date has passed past date.
Apart from that how can i do this
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hi Gopal,
Using a UI Policy for date validation logic can be tricky because UI Policies are primarily designed for field behavior (Visible/Mandatory/Read-only), not for complex date math or validation feedback.
The Best Practice: You should use an onChange Client Script. This allows you to catch the date immediately after the user picks it, compare it against the current time using ServiceNow's helper functions (which handle date formats automatically), and clear the field if it is invalid.
Here is the script you can apply to both the Problem Task and Change Task tables.
Solution: onChange Client Script
Table: Problem Task [problem_task] (Repeat for Change Task)
Type: onChange
Field Name: Due date [due_date]
UI Type: All
Script:
function onChange(control, oldValue, newValue, isLoading, isTemplate) { if (isLoading || newValue === '') { return; } // 1. Get the user's date format (e.g., dd-MM-yyyy HH:mm:ss) // We use the helper function 'getDateFromFormat' provided by ServiceNow var format = g_user_date_time_format; var dateMs = getDateFromFormat(newValue, format); // 2. Get the current time in milliseconds var now = new Date().getTime(); // 3. Compare: If Selected Date is less than Now if (dateMs < now && dateMs != 0) { // Clear the invalid value g_form.clearValue('due_date'); // Show an error message specifically under the field g_form.showFieldMsg('due_date', 'The Due Date cannot be in the past. Please select a future date.', 'error'); } else { // If valid, clear any previous error messages g_form.hideFieldMsg('due_date'); } }
Optional: Backend Protection (Business Rule)
Client Scripts only work on the Form view. If you want to prevent users from setting past dates via List Edit or API, you should also add an onBefore Business Rule.
When: Before Insert/Update
Condition: Due date changes
Script:
if (current.due_date < gs.nowDateTime()) { gs.addErrorMessage('Due date cannot be in the past.'); current.setAbortAction(true); }
Summary: The Client Script provided above will give you the smooth user experience you are looking for (clearing the field and showing a clean error message) without the limitations of a UI Policy.
If this script solves your validation issue, please mark it as Accepted Solution.
Best regards,
Brandão.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
I have used the above same script,
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
var format = g_user_date_time_format;
var dateMs = getDateFromFormat(newValue, format);
var now = new Date().getTime();
if (dateMs < now && dateMs != 0) {
// g_form.clearValue('due_date');
g_form.showFieldMsg('due_date', 'The Due Date cannot be in the past. Please select a future date', 'error');
} else {
g_form.hideFieldMsg('due_date');
}
}Now what 's happening is If I select today, then also it is showing fieldmessage.
If I select yesterday, then it is showing field message and error message also, but If I try to save that form, it is saving
Any changes required here
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hi @Gopal14 ,
You absolutely nailed it in your observation!
The Root Cause:
Why it saves: You are using g_form.clearValue(). Since the field is not mandatory, the system treats "Empty" as a valid state and allows the save.
Why it clears old records: Your logic (especially if using UI Policy) runs when the form loads. A date that was valid yesterday is "past" today, so the script/policy blindly wipes it out when you open the record.
Why "Today" fails: The script compares timestamps (Time). 12:00 PM (Now) is greater than 00:00 AM (Today selected), so it blocks today.
The Solution: You need a script that ignores time, ignores existing database values (only checks changes), and handles the mandatory state.
Use this onChange Client Script:
Type: onChange
Field: Due date
function onChange(control, oldValue, newValue, isLoading, isTemplate) { // 1. Safety check: Stop if loading OR if value is empty if (isLoading || newValue === '') { return; } // 2. CRITICAL: Only validate if the user actually CHANGED the value. // This prevents the script from clearing historical dates when you open the form tomorrow. if (newValue == oldValue) { return; } // 3. Get User Format and Setup Dates var format = g_user_date_time_format; // or g_user_date_format depending on field type var dateMs = getDateFromFormat(newValue, format); // Create Date Objects to compare "Day vs Day" (ignoring time) var selectedDate = new Date(dateMs); selectedDate.setHours(0,0,0,0); var today = new Date(); today.setHours(0,0,0,0); // Strip time from "Now" // 4. Compare if (selectedDate < today) { g_form.showFieldMsg('due_date', 'Past dates are not allowed. Please select Today or Future.', 'error'); g_form.clearValue('due_date'); // 5. THE FIX FOR SAVING: Make it mandatory if they try to cheat // This forces them to pick a valid date before saving g_form.setMandatory('due_date', true); } else { g_form.hideFieldMsg('due_date'); } }
Why this works:
selectedDate.setHours(0,0,0,0): Fixes the "Today" bug.
if (newValue == oldValue): Fixes the "Old records getting cleared" bug.
setMandatory(true): Fixes the "User can save empty" bug.
If this script solves the logic logic loop, please mark it as Accepted Solution.
Best regards,
Brandão.
=D
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
2 weeks ago
@Itallo Brandão This code working fine in Native view, But when we are testing in SOW(service operations workspace) it is not working

