Skip to content
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

Conditional visibility but unconditional validation #846

Open
theMikeD opened this issue Oct 2, 2022 · 4 comments
Open

Conditional visibility but unconditional validation #846

theMikeD opened this issue Oct 2, 2022 · 4 comments

Comments

@theMikeD
Copy link

theMikeD commented Oct 2, 2022

Consider the following code, in which the manual option of ip_option is used to conditionally display manual_ip which is a text box to allow the user to enter an IP address:

'children'                  => array(
'ip_presets' => new \Fieldmanager_Group(
	array(
		'label'       => 'Use Presets',
		'description' => '<p>These allow you to force IP addresses using presets for in- and out-of-market.</p>',
		'children'    => array(
			'ip_option' => new \Fieldmanager_Radios(
				array(
					'options' => array(
						'default' => 'Use the IP address calculated by the system',
						'in_market' => 'Force In-Market (Portland, ME: 154.6.12.147)',
						'out_of_market' => 'Force Out-of-Market (Chicago, Il: 181.214.165.13)',
						'manual' => 'Enter an IP address to use',
					),
				)
			),
			'manual_ip' => new \Fieldmanager_TextField(
				'Enter IP address',
				array(
					'display_if'  => array(
						'src'   => 'ip_option',
						'value' => 'manual',
					),
					'attributes' => array(
						'size'       => 25,
					),
					// Validation functions must return true or false.
					'validate'   => array(
						function( $value ) {
							return filter_var( sanitize_text_field( $value ), FILTER_VALIDATE_IP );
						},
					),
					// Sanitization functions must return true or false.
					'sanitize'    => fn( $value ) => filter_var( sanitize_text_field( $value ), FILTER_VALIDATE_IP ),
				)
			),
		),
		'escape'      => array(
			'description' => 'wp_kses_post',
		),
		'description_after_element' => false,
	),
),

If the user selects the manual option and enters a invalid IP address, you get the warning as expected:

Screen-Shot-2022-10-02-at-11-58-58-AM.jpg

Now the user hits the back button, and selects one of the other options (which hides the text entry) and saves...and they get the warning again. This is because TextField validate function is run even when the display_if is false.

So here are my questions

  1. assuming this is by design, how can the validation be conditional too?
  2. if a user selects one of the other radio items, is there a way to clear the value in manual_ip in the UX?
  3. if a user clears the value if manual_ip, and saves, is there a way to set ip_option to default?
@dlh01
Copy link
Member

dlh01 commented Oct 3, 2022

Hey @theMikeD!

  1. I don't believe it's currently possible to run the validation callback conditionally, at least not conditionally based on a value submitted from a sibling field. You might be able to hack your way into it by validating the data inside the fm_presave_alter_values filter — see Validation functions #578.

    On the other hand, it also seems preferable for the validation to run unconditionally. For example, in the future, someone might try to use manual_ip for a new purpose without reference to ip_option. It'd be unexpected, I think, for a potentially invalid value to be there in spite of the validation callback.

  2. (and 3.) Also not currently possible, as far as I know. You'd have to include some custom JS that listens for changes.

@dlh01
Copy link
Member

dlh01 commented Oct 3, 2022

Actually, you might be able to use the fm_presave_alter_values filter to accomplish (3) as well, if you're OK with it happening after saving and not in the UX.

@theMikeD
Copy link
Author

theMikeD commented Oct 3, 2022

Thanks for the tips! The main issue is that the manually-entered IP is only required if that option is selected; in all other cases it should be set to null...but the validator is checking for that and fails if it's null/empty, because if the manual option is selected, an empty value correctly fails the filter_var check.

@theMikeD
Copy link
Author

theMikeD commented Dec 8, 2022

@dlh01 I'm having something similar now and I wonder if it's related. If I create a repeater using

'limit'          => 10,     // max number allowed
'collapsible'    => true,
'collapsed'      => false,
'minimum_count'  => 0,      // how many to start with
'extra_elements' => 0,      // how many blank ones to show in addition to the filled in ones

and one of the fields in the group added by the repeater has

'attributes'  => array(
	'required' => true,
),

then the form never saves, because it's trying to enforce required on a field that doesn't exist in the ui ( because of 'minimum_count' => 0, )

Is this the same problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants