thausmann Posted May 9 Share Posted May 9 (edited) I'm trying to create a newsletter signup form with the API and validate/sanitize it with form->processInput. It only has two inputs: email and a consent checkbox. When I submit the form with an empty or malformed email, I get form errors after calling processInput. But when I don't check the checkbox, the submission gets through without errors. It seems like setting required(true) on the checkbox has no effect. Is this normal and I have to manually sanitize checkboxes? I'd expect it to behave like the other input and automatically create an error. These functions are inside a page class: public function createForm() { $modules = $this->wire()->modules; /** @var InputfieldForm */ $form = $modules->get('InputfieldForm'); $form->method = 'post'; $form->action = $this->url; /** @var InputfieldEmail */ $field = $modules->get('InputfieldEmail'); $field->label = __('Email*'); $field->attr('id+name', 'email'); $field->attr('placeholder', $field->label); $field->required(true); $field->requiredAttr(true); $form->append($field); /** @var InputfieldCheckbox */ $field = $modules->get('InputfieldCheckbox'); $field->label = '%consent_label%'; $field->attr('id+name', 'newsletter_consent'); $field->attr('required', true); $field->required(true); $form->append($field); ... return $form; } public function progressInput() { $input = wire()->input; $this->form = $this->createForm(); if($input->post('newsletter_submit')) { // Process the form with current input $this->form->processInput($input->post); $errors = $this->form->getErrors(); if(!count($errors)) { $this->subscribeToMailchimp(); } } } Template: $page->progressInput(); $errors = $page->form->getErrors(true); if(count($errors) > 0) { foreach($errors as $error) { echo $error; } } echo $page->form->render(); Edited May 9 by thausmann Link to comment Share on other sites More sharing options...
Jan Romero Posted May 9 Share Posted May 9 (edited) Idk, it works as expected for me. The only thing I changed from your code was removing $field->attr('required', true), so the browser would let me send without checking the box. And making everything into plain functions so I could just put them in a template. The required-check happens in InputfieldWrapper and there is no special logic for checkboxes (InputfieldCheckbox::processInput() will find no errors, leaving it to InputfieldWrapper). You can check it out here: https://github.com/processwire/processwire/blob/44fcf13ea2d7f14a04eed54c29afcc79eb46ec45/wire/core/InputfieldWrapper.php#L1304 // check if a value is required and field is empty, trigger an error if so if($child->attr('name') && $child->getSetting('required') && $child->isEmpty()) { $requiredLabel = $child->getSetting('requiredLabel'); if(empty($requiredLabel)) $requiredLabel = $this->requiredLabel; $child->error($requiredLabel); } The error value will be “%consent_label% - Missing required value”. As we can see, this depends on InputfieldCheckbox::isEmpty(), which simply negates InputfieldCheckbox::checked(). The rest is a little weird, but suffice it to say that the posted form data is examined using PHP’s empty(), so if any value at all has been sent for the checkbox (“newsletter_consent”), it’ll pass the required check. By default the value would be the string '1', and if unchecked, as we know, no mention of the checkbox would be sent at all. Edited May 10 by Jan Romero 1 Link to comment Share on other sites More sharing options...
thausmann Posted May 12 Author Share Posted May 12 Thanks so much Jan for double checking! You found the culprit: removing $field->attr('required', true); really makes the key difference. When I was testing, I bypassed the browser check by removing the required attribute through the dev tools. The solution is to use $field->requiredAttr = true; instead! One of those seem to have some side effects that cause the unwanted behaviour. In the past, I had a syntax error because I used $field->requiredAttr(true); which works for text inputs, but not checkboxes, interestingly. After checking the docs again, it's supposed to just be a property and not a method call. Which is a bit confusing because there is $field->required(true). Link to comment Share on other sites More sharing options...
Jan Romero Posted yesterday at 01:46 PM Share Posted yesterday at 01:46 PM Interesting. I think I’ve figured out why this happens and I opened an issue here: https://github.com/processwire/processwire-issues/issues/2074 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now