The oldValue parameter in onChange client scripts gives you the field's value before the user's change, but it's undefined during form load — even for existing records with data. Most developers assume oldValue will contain the database value when editing existing records, but it only captures values after the form has loaded and the user makes their first change. This behavior exists because the client script engine doesn't populate oldValue until after the first user interaction with each field.
When to use this
- When you need to compare before and after values to trigger conditional logic in real-time
- When building audit trails or change notifications that must fire immediately on field changes
- When implementing field validation that depends on the transition between specific values
- When you need to show contextual messages about what changed during the user's current session
When NOT to use this
- Don't rely on
oldValuefor business rules that must capture all changes — usepreviousobject in server-side business rules instead - Don't use this when you need the original database value on form load — use
g_scratchpadpopulated by a display business rule - Don't use this for complex field interdependencies — use
onSubmitvalidation where you can check multiple field states together - Don't process
onChangeevents duringisLoading— you'll get false positives from form population
Key behaviors and gotchas
- The full
onChangesignature is(control, oldValue, newValue, isLoading, isTemplate)— always checkisLoadingandisTemplatebefore processing - For reference fields,
oldValuecontains thesys_id, not the display value — usegetReference()to get display values for comparison - Choice field
oldValuecontains the actual choice value (like'2'forIn Progress), not the display label - Empty reference fields return empty string
''inoldValue, notnullorundefined - Date/time fields in
oldValueare formatted strings in the user's session format, not raw database values - Multiple rapid changes to the same field will have
oldValueas the value from the previousonChange, not the original form load value
Never assume oldValue exists without checking — it's undefined on form load even for existing records. Always use typeof oldValue === 'undefined' before attempting to use the value, or your onChange logic will fail silently on the user's first field interaction.
Enjoying this? Get one deep-dive per week.
Join 1,000+ ServiceNow pros — scripts, GlideRecord patterns, Flow Designer techniques, and career moves. Free.