Skip to content

Lite: Fix number field validation appearing when min/max values are empty#2664

Merged
Crabcyborg merged 11 commits into
masterfrom
fix-number-validation-popup
Jun 5, 2026
Merged

Lite: Fix number field validation appearing when min/max values are empty#2664
Crabcyborg merged 11 commits into
masterfrom
fix-number-validation-popup

Conversation

@shervElmi
Copy link
Copy Markdown
Contributor

@shervElmi shervElmi commented Dec 17, 2025

Pro PR

https://github.com/Strategy11/formidable-pro/pull/6137

Summary by CodeRabbit

  • New Features
    • Added validation for range and numeric field settings in the form builder: invalid configs (e.g., min ≥ max, non-positive or oversized step) now show clear error messages and highlight affected fields.
    • Improved field-type/ID detection to make validations more reliable.
    • Validation utilities are now exposed so other admin tools can trigger or reuse these checks.

@shervElmi shervElmi self-assigned this Dec 17, 2025
@shervElmi shervElmi marked this pull request as ready for review December 17, 2025 16:12
@shervElmi shervElmi requested a review from Crabcyborg December 17, 2025 16:12
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 17, 2025

Too much diff to scan? Review this PR in Change Stack to start with the highest-impact changes.

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: db5f5cd6-6b5d-4896-b8a6-08acf8a95400

📥 Commits

Reviewing files that changed from the base of the PR and between 382a5bc and 6573fc5.

📒 Files selected for processing (2)
  • js/formidable_admin.js
  • js/src/admin/settings/validateRangeSettings.js

📝 Walkthrough

Walkthrough

Adds client-side validation for range and step settings: a generic validator that shows errors in the info modal and restores focus, range/step-specific checks (min < max, step bounds), builder wiring to run validations on change, and a public API under frmAdminBuild.settings.validate.

Changes

Range Settings Validation

Layer / File(s) Summary
Generic Field Validation Framework
js/src/admin/settings/validateField.js
validateField(field, getError) runs a validation callback, shows the info modal on error, toggles the frm_invalid_field CSS class, and restores focus after modal dismissal via focusFieldOnModalDismiss.
Range and Step Validators
js/src/admin/settings/validateRangeSettings.js
getRangeSettingsDefaults derives numeric defaults with frm_range_settings_defaults filter support. validateNumberRangeSetting enforces min < max for number-range fields. validateStepSetting enforces step > 0 and that step ≤ (max - min). validateRangeSettings runs both and applies frm_validate_range_settings.
Builder Integration and Public API
js/src/admin/admin.js
Imports validation utilities, invokes validateRangeSettings(target) in handleBuilderChangeEvent, and exposes validation functions under frmAdminBuild.settings.validate for external use.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🐰 New validators jump and play,

min and max kept in their place,
steps counted true, not astray,
modals blink and return my gaze,
builder hums with validation grace.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change—adding validation utilities to fix number field validation appearing when min/max values are empty, which is reflected throughout the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-number-validation-popup
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch fix-number-validation-popup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
js/src/admin/admin.js (2)

8458-8463: Builder change handler now conditionally runs range/step validation

Hooking validateNumberRangeSetting(target) and validateStepSetting(target) from handleBuilderChangeEvent behind ! frmGlobal.proIsConnected looks safe: both helpers guard on the element’s context (.frm-number-range / .frm-step) and will no-op for unrelated changes, so the extra work on the builder change stream is minimal while avoiding duplicate validation when Pro is connected.

If you want to tighten this further later, you could short‑circuit on target.closest('.frm-number-range, .frm-step') before calling either validator to avoid two function calls for clearly unrelated inputs.


11170-11180: Public frmAdminBuild.settings.validate API looks good; fill in @since

Exposing validateField, getRangeSettingsDefaults, validateNumberRangeSetting, and validateStepSetting under frmAdminBuild.settings.validate is a reasonable and coherent namespace, and aligns with how other helpers are surfaced from this module. The only nit is the JSDoc @since x.x placeholder above it; consider replacing this with the actual release version so downstream consumers know when this API became available.

js/src/admin/settings/validateRangeSettings.js (1)

51-120: Consider extracting common field lookup pattern.

Both validateNumberRangeSetting and validateStepSetting share a similar pattern for retrieving singleSettings, fieldId, and related input elements. Consider extracting this into a shared helper function to reduce duplication.

Example refactoring:

/**
 * Gets common field validation context.
 */
function getFieldContext( field, containerClass ) {
	if ( ! field.closest( containerClass ) ) {
		return null;
	}
	
	const singleSettings = field.closest( '.frm-single-settings' );
	const fieldId = getFieldId( singleSettings );
	
	return fieldId ? { singleSettings, fieldId } : null;
}

export function validateNumberRangeSetting( field ) {
	const context = getFieldContext( field, '.frm-number-range' );
	if ( ! context ) {
		return;
	}
	
	const { singleSettings, fieldId } = context;
	// ... rest of validation
}
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d6fde5 and 43eed37.

⛔ Files ignored due to path filters (1)
  • js/formidable_admin.js.map is excluded by !**/*.map, !**/*.map
📒 Files selected for processing (5)
  • classes/helpers/FrmAppHelper.php (1 hunks)
  • js/src/admin/admin.js (3 hunks)
  • js/src/admin/settings/utils.js (1 hunks)
  • js/src/admin/settings/validateField.js (1 hunks)
  • js/src/admin/settings/validateRangeSettings.js (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
js/src/admin/admin.js (1)
js/src/admin/settings/validateRangeSettings.js (2)
  • validateNumberRangeSetting (51-79)
  • validateStepSetting (88-120)
js/src/admin/settings/validateRangeSettings.js (1)
js/src/admin/settings/validateField.js (1)
  • validateField (11-21)
🔇 Additional comments (5)
classes/helpers/FrmAppHelper.php (1)

3868-3868: LGTM. The proIsConnected addition correctly exposes the Pro connection status to frontend validation logic. The implementation gates number field range and step validation to run only when Pro is disconnected, with proper handling of empty min/max values via default values. The validation logic is sound and works correctly in both connected and disconnected states.

js/src/admin/admin.js (1)

4-8: New validation imports are consistent and correctly scoped

The new require calls for validateField, getRangeSettingsDefaults, validateNumberRangeSetting, and validateStepSetting match the existing CommonJS pattern in this file and are only used where needed; no issues from a bundling or scoping perspective.

js/src/admin/settings/utils.js (1)

11-30: LGTM! Good use of optional chaining.

Both utility functions properly handle null/undefined inputs using optional chaining, making them safe to call in various contexts without explicit null checks by the caller.

js/src/admin/settings/validateRangeSettings.js (2)

72-78: LGTM! Correctly handles empty values.

The validation logic properly addresses the PR objective by using fallback defaults (0 for min, 9999999 for max) when fields are empty. This ensures validation doesn't trigger incorrectly when min/max values are not provided, while still catching actual invalid entries.


104-119: LGTM! Step validation logic is sound.

The validation correctly ensures step is positive and doesn't exceed the maximum value, while gracefully handling empty inputs using defaults.

Comment thread js/src/admin/settings/validateField.js
Comment thread js/src/admin/settings/validateRangeSettings.js
@Crabcyborg Crabcyborg added this to the 6.28 milestone Jan 5, 2026
@Crabcyborg Crabcyborg modified the milestones: 6.28, 6.29 Feb 12, 2026
@Crabcyborg Crabcyborg modified the milestones: 6.29, 6.30 Mar 9, 2026
@deepsource-io
Copy link
Copy Markdown

deepsource-io Bot commented Jun 5, 2026

DeepSource Code Review

We reviewed changes in b7cd07c...b3ae6ed on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
PHP Jun 5, 2026 8:32p.m. Review ↗
JavaScript Jun 5, 2026 8:32p.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

Comment on lines +72 to +78
return validateField( field, () => {
const { minNum, maxNum } = getRangeSettingsDefaults( singleSettings );

return parseFloat( minValueInput.value || minNum ) >= parseFloat( maxValueInput.value || maxNum )
? __( 'Minimum value cannot be greater than or equal to maximum value.', 'formidable' )
: '';
} );
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function 'validateNumberRangeSetting' expected no return value


Any code paths that do not have explicit returns will return undefined. It is recommended to replace any implicit dead-ends that return undefined with a return null statement.

Comment on lines +104 to +119
return validateField( field, () => {
const { step, maxNum } = getRangeSettingsDefaults( singleSettings );
const stepInputValue = parseFloat( stepInput.value || step );
if ( stepInputValue <= 0 ) {
return __( 'Step value must be greater than 0.', 'formidable' );
}

const maxValueInput = document.querySelector( `[name="field_options[maxnum_${ fieldId }]"]` );
if ( ! maxValueInput ) {
return '';
}

return stepInputValue > parseFloat( maxValueInput.value || maxNum )
? __( 'Step value must be less than maximum value.', 'formidable' )
: '';
} );
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function 'validateStepSetting' expected no return value


Any code paths that do not have explicit returns will return undefined. It is recommended to replace any implicit dead-ends that return undefined with a return null statement.

Comment on lines +104 to +123
return validateField( field, () => {
const { step, minNum, maxNum } = getRangeSettingsDefaults( singleSettings );
const stepInputValue = parseFloat( stepInput.value || step );
if ( stepInputValue <= 0 ) {
return __( 'Step value must be greater than 0.', 'formidable' );
}

const maxValueInput = document.querySelector( `[name="field_options[maxnum_${ fieldId }]"]` );
if ( ! maxValueInput ) {
return '';
}

const minValueInput = document.querySelector( `[name="field_options[minnum_${ fieldId }]"]` );
const minValue = parseFloat( minValueInput?.value || minNum );
const maxValue = parseFloat( maxValueInput.value || maxNum );

return stepInputValue > maxValue - minValue
? __( 'Step value cannot be greater than the difference between the minimum and maximum values.', 'formidable' )
: '';
} );
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function 'validateStepSetting' expected no return value


Any code paths that do not have explicit returns will return undefined. It is recommended to replace any implicit dead-ends that return undefined with a return null statement.

Copy link
Copy Markdown
Contributor

@Crabcyborg Crabcyborg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made several changes.

This no longer requires a JS var to determine if Pro is connected.

I also made some changes in Pro. When Lite wasn't up to date, the errors were not appearing.

And the step validation was weird. I updated it to check for the difference between max and min.

@Crabcyborg Crabcyborg merged commit f1aebec into master Jun 5, 2026
19 of 22 checks passed
@Crabcyborg Crabcyborg deleted the fix-number-validation-popup branch June 5, 2026 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants