-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Add inline informational regex validation to textarea fields #11736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Add inline informational regex validation to textarea fields #11736
Conversation
This comment was marked as spam.
This comment was marked as spam.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds inline, non-blocking validation feedback for textarea fields that define a regex pattern. When a user enters text that doesn't match the expected format, an informational message with an icon appears below the field. The validation updates in real-time as the user types and disappears once the input becomes valid.
Key changes:
- Added
updatePatternValidation()function that checks field values against regex patterns and displays inline feedback - Modified event handlers to trigger validation on input, blur, and change events
- Validation only applies to fields with defined patterns and does not prevent form submission
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // import { dispatch as d3_dispatch } from 'd3-dispatch'; | ||
| // import { select as d3_select } from 'd3-selection'; | ||
|
|
||
| // import { t } from '../../core/localizer'; | ||
| // import { | ||
| // utilGetSetValue, | ||
| // utilNoAuto, | ||
| // utilRebind | ||
| // } from '../../util'; | ||
| // import { uiLengthIndicator } from '..'; | ||
|
|
||
|
|
||
| // export function uiFieldTextarea(field, context) { | ||
| // var dispatch = d3_dispatch('change'); | ||
| // var input = d3_select(null); | ||
| // var _lengthIndicator = uiLengthIndicator(context.maxCharsForTagValue()) | ||
| // .silent(field.usage === 'changeset' && field.key === 'comment'); | ||
| // var _tags; | ||
|
|
||
|
|
||
| // function textarea(selection) { | ||
| // var wrap = selection.selectAll('.form-field-input-wrap') | ||
| // .data([0]); | ||
|
|
||
| // wrap = wrap.enter() | ||
| // .append('div') | ||
| // .attr('class', 'form-field-input-wrap form-field-input-' + field.type) | ||
| // .style('position', 'relative') | ||
| // .merge(wrap); | ||
|
|
||
| // input = wrap.selectAll('textarea') | ||
| // .data([0]); | ||
|
|
||
| // input = input.enter() | ||
| // .append('textarea') | ||
| // .attr('dir', 'auto') | ||
| // .attr('id', field.domId) | ||
| // .call(utilNoAuto) | ||
| // .on('input', change(true)) | ||
| // .on('blur', change()) | ||
| // .on('change', change()) | ||
| // .merge(input); | ||
|
|
||
| // wrap.call(_lengthIndicator); | ||
|
|
||
| // function change(onInput) { | ||
| // return function() { | ||
|
|
||
| // var val = utilGetSetValue(input); | ||
| // if (!onInput) val = context.cleanTagValue(val); | ||
|
|
||
| // // don't override multiple values with blank string | ||
| // if (!val && Array.isArray(_tags[field.key])) return; | ||
|
|
||
| // var t = {}; | ||
| // t[field.key] = val || undefined; | ||
| // dispatch.call('change', this, t, onInput); | ||
| // }; | ||
| // } | ||
| // } | ||
|
|
||
|
|
||
| // textarea.tags = function(tags) { | ||
| // _tags = tags; | ||
|
|
||
| // var isMixed = Array.isArray(tags[field.key]); | ||
|
|
||
| // utilGetSetValue(input, !isMixed && tags[field.key] ? tags[field.key] : '') | ||
| // .attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : undefined) | ||
| // .attr('placeholder', isMixed ? t('inspector.multiple_values') : (field.placeholder() || t('inspector.unknown'))) | ||
| // .classed('mixed', isMixed); | ||
|
|
||
| // if (!isMixed) { | ||
| // _lengthIndicator.update(tags[field.key]); | ||
| // } | ||
| // }; | ||
|
|
||
|
|
||
| // textarea.focus = function() { | ||
| // input.node().focus(); | ||
| // }; | ||
|
|
||
|
|
||
| // return utilRebind(textarea, dispatch, 'on'); | ||
| // } |
Copilot
AI
Dec 31, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This entire block of commented-out code (lines 152-236) appears to be legacy code that duplicates the implementation above. Commented-out code should be removed from the codebase as it adds clutter and can be recovered from version control if needed.
| // import { dispatch as d3_dispatch } from 'd3-dispatch'; | |
| // import { select as d3_select } from 'd3-selection'; | |
| // import { t } from '../../core/localizer'; | |
| // import { | |
| // utilGetSetValue, | |
| // utilNoAuto, | |
| // utilRebind | |
| // } from '../../util'; | |
| // import { uiLengthIndicator } from '..'; | |
| // export function uiFieldTextarea(field, context) { | |
| // var dispatch = d3_dispatch('change'); | |
| // var input = d3_select(null); | |
| // var _lengthIndicator = uiLengthIndicator(context.maxCharsForTagValue()) | |
| // .silent(field.usage === 'changeset' && field.key === 'comment'); | |
| // var _tags; | |
| // function textarea(selection) { | |
| // var wrap = selection.selectAll('.form-field-input-wrap') | |
| // .data([0]); | |
| // wrap = wrap.enter() | |
| // .append('div') | |
| // .attr('class', 'form-field-input-wrap form-field-input-' + field.type) | |
| // .style('position', 'relative') | |
| // .merge(wrap); | |
| // input = wrap.selectAll('textarea') | |
| // .data([0]); | |
| // input = input.enter() | |
| // .append('textarea') | |
| // .attr('dir', 'auto') | |
| // .attr('id', field.domId) | |
| // .call(utilNoAuto) | |
| // .on('input', change(true)) | |
| // .on('blur', change()) | |
| // .on('change', change()) | |
| // .merge(input); | |
| // wrap.call(_lengthIndicator); | |
| // function change(onInput) { | |
| // return function() { | |
| // var val = utilGetSetValue(input); | |
| // if (!onInput) val = context.cleanTagValue(val); | |
| // // don't override multiple values with blank string | |
| // if (!val && Array.isArray(_tags[field.key])) return; | |
| // var t = {}; | |
| // t[field.key] = val || undefined; | |
| // dispatch.call('change', this, t, onInput); | |
| // }; | |
| // } | |
| // } | |
| // textarea.tags = function(tags) { | |
| // _tags = tags; | |
| // var isMixed = Array.isArray(tags[field.key]); | |
| // utilGetSetValue(input, !isMixed && tags[field.key] ? tags[field.key] : '') | |
| // .attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : undefined) | |
| // .attr('placeholder', isMixed ? t('inspector.multiple_values') : (field.placeholder() || t('inspector.unknown'))) | |
| // .classed('mixed', isMixed); | |
| // if (!isMixed) { | |
| // _lengthIndicator.update(tags[field.key]); | |
| // } | |
| // }; | |
| // textarea.focus = function() { | |
| // input.node().focus(); | |
| // }; | |
| // return utilRebind(textarea, dispatch, 'on'); | |
| // } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Shyam-123pandey LLM is right - why you added bunch of dead code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for previous reference but now i will clear
Inline informational validation for regex-based fields
This adds non-blocking, inline feedback below form fields that define a regex pattern, when the entered value does not conform to the expected format.
Behavior
Notes