Laravel form validation wrong when using checkbox to hide/show fields causes - forms

I have a form in Laravel 6 that uses a checkbox to hide/show additional fields. So the fields are hidden, but when the user checks the box ('attorney') and the fields appear, they are required. Otherwise, when they are hidden (checkbox unchecked) they are not required.
The following are the validation rules for the form:
public function rules()
{
return [
'name' => 'required',
'email' => 'required|email|unique:users,email',
'password' => 'required',
'role' => 'required',
'role.*' => 'exists:roles,id',
'attorney' => 'nullable',
'bar_number' => 'nullable|required_if:attorney,1',
'law_firm_email' => 'nullable|required_if:attorney,1',
'law_firm_address' => 'nullable|required_if:attorney,1',
'law_firm_name' => 'nullable|required_if:attorney,1',
];
}
This hide/unhide works fine for users who check the box, and the form works for those that submit that extra info, but for those that don't check the box (those extra fields remain hidden) the form fails with the error "The bar number must be a string" (bar number is first field in list). The hidden fields are still being validated even though the checkbox is unchecked (the condition required_if should be false). I have tried 'checked' and 'on' for the checkbox value, same result.
This is the checkbox in the view:
<div class="col-md-6"></br>
<input id="attorney" type="checkbox" name="attorney" value="{{ old('attorney') }}"> Check if registering a law firm
#if ($errors->has('attorney'))
<span class="help-block">
<strong>{{ $errors->first('attorney') }}</strong>
</span>
#endif
</div>
This is the JavaScript that hides/shoes the DIV with the additional fields:
<script>
$(document).ready(function() {
$('input[name="attorney"]').change(function() {
if(this.checked) {
$('#bar_number_div').fadeIn('fast');
} else {
$('#bar_number_div').fadeOut('fast');
}
});
});
</script>
The JavaScript works fine as expected. The validation config is my issue.
There are no errors in the console.
I thought the required_if condition in the validation rules should work as expected, i.e., when the checkbox "attorney" is unchecked the required validation rule is not applied.

You can try with on in required_if
public function rules() {
return [
'name' => 'required',
'email' => 'required|email|unique:users,email',
'password' => 'required',
'role' => 'required',
'role.*' => 'exists:roles,id',
'attorney' => 'nullable',
'bar_number' => 'nullable|required_if:attorney,on',
'bar_number' => 'nullable|required_if:attorney,on',
'law_firm_email' => 'nullable|required_if:attorney,on',
'law_firm_address' => 'nullable|required_if:attorney,on',
'law_firm_name' => 'nullable|required_if:attorney,on',
];
}
Remove value from input checkbox
<input id="attorney" type="checkbox" name="attorney">

Related

Symfony: Hide/Show form element dependent on dropdown selection with database entries

I hope my title is proper: I have a dropdown, that comes from a form as an EntityType and the values are from an entity class. Code:
->add('type', EntityType::class, array(
'class' => 'DocumentBundle:DocumentType',
'label' => 'label.type',
'property' => 'translationKey',
'required' => true,
'multiple' => false,
'expanded' => false,
'empty_value' => 'label.select_type',
'choice_translation_domain' => 'Documents'
))
->add('vka_number', 'text', array(
'label' => 'label.vka_number',
'required' => false,
'translation_domain' => 'Documents'))
the second one is a text field (vka_number) that I only want to be shown when a specific value from that dropdown is selected
in my twig template I render the elements:
<div class="row">
<div class="col-md-6" id="documentDropdown">
{{ form_row(form.type) }}
</div>
<div class="col-md-6" id="vka">
{{ form_row(form.vka_number) }}
</div>
</div>
I was thinking about a javascript function like that:
<script>
$(document).ready(function(){
$('#documentDropdown').on('change', function(){
if (this.value == 'Contract')
{
$('#vka').show();
}
else {
$('#vka').hide();
}
});
});
</script>
but it's not working and I think this is because it can't access the values from the dropdown since they are not hard coded but database entries.
'Contract' would be the entry (id=1) that "makes" the vka_number text field appear.
I copied the html code from your previous question Sonja, and you seem to be continuing to ask the same question. I used that code in this jsfiddle:
https://jsfiddle.net/alvinbunk/to9qodwx/
You can use jsfiddle to experiment with your jQuery code to figure out what is wrong. As you can see the code does work and does hide the vka id division. it really has nothing to do with the fact that values are from the database. Make sure you don't have duplicate ids in various elements in your html code. Use "view source" in your browser to see the rendered code.
By the way I spent at least 15 minutes on this answer, and also 15 - 30 minutes on the other one. be aware that people on StackOverflow are very busy, and it's good to ask your questions very clearly.
EDIT #2 - Based on comments
Use this jQuery code:
<script>
$(document).ready(function(){
$('#documentDropdown').on('change', function(){
if (this.value == '1')
{
$('#vka').show();
}
else {
$('#vka').hide();
}
});
});
</script>
That should work.
Here's my javascript function that eventually solved my problem.
$(document).ready(function () {
$('#type ').change(function() {
if ($('select[id$="_type"]>option:selected').text() == "Contract") {
$('#vka_number ').show();
}
else {
$('#vka_number').hide();
}
});
});

cakephp 3: change class input error

I build my form template according the documentation. It seemed everything was fine until I get fields errors. Now I have two problems:
How can I change the class name of the forms fields when they get error?
Solution:
$this->loadHelper('Form', [
'templates' => 'your_template_file',
'errorClass' => 'your-class',
]);
How can I set escape => false in the error-message from cakephp, when the field get error? Because I have icon within that div, such as
<div class="error-message"><i class="fa fa-times"></i> My error</div>
Well, I got part of th solution. To escape HTML I could put $this->Form->error('field', null, ['escape' => false]); in all fields, but it´s a hard manually task. I´d like to keep escape with default of all fields errors. I could edit the FormHelper.php class. However, I think that is not good idea.
My form template is:
'formStart' => '<form {{attrs}} class="form-horizontal" novalidate>',
'inputContainer' => '{{content}}',
'input' => '<input type="{{type}}" name="{{name}}" {{attrs}} class="form-control"/>',
'checkbox' => '<input type="checkbox" value="{{value}}" name="{{name}}" {{attrs}}/>',
'textareaContainerError' => '{{content}}',
'textarea' => '<textarea name="{{name}}" {{attrs}} class="form-control"></textarea>',
'select' => '<select name="{{name}}" {{attrs}} class="form-control">{{content}}</select>',
'button' => '<button {{attrs}} class="btn btn-primary">{{text}}</button>',
'nestingLabel' => '{{input}}',
'formGroup' => '{{input}}',
to the second part of the question: you can extend FormHelper like in code below, so that escape will be set to false by default
// extended FormHelper, this goes in src/View/Helper
namespace App\View\Helper;
use Cake\View\Helper;
class MyFormHelper extends Helper\FormHelper
{
public function error($field, $text = null, array $options = [])
{
if (!isset($options['escape'])) {
$options['escape'] = false;
}
return parent::error($field, $text, $options);
}
}
next create alias for this helper in AppController.php
public $helpers = [
'Form' => ['className' => 'MyForm']
];
this also allows you to add more customization of your own and at any time, you can go back to default implementation of FormHelper, just remove that alias from AppController.php.
For those who wants an 'easy solution' to escape error message on some fields, you cant simply set escape options to false :
<?= $this->Form->input('email', [
"label" => "Email",
"error" => [
"escape" => false
]
]) ?>

CakePHP Show Validation Message on Hidden Field

In my form I've created a hidden field:
echo $this->Form->hidden('editor_rating', array('value' => 0));
Which outputs:
In my model I've created a validation rule:
'editor_rating' => array(
'rule' => array('comparison', 'greater or equal', 1),
'message' => 'Please choose a valid Editor Rating'
)
When I submit the form the hidden field has an error class added, but no visible change and no error message:
<input id="ListingEditorRating" class="form-error" type="hidden" value="0" name="data[Listing][editor_rating]">
How can I make this error message visible or even attach it to a different div?
FormHelper::error
For use cases where Form->input or Form->inputs are not used you can render errors explicitly:
if ($this->Form->isFieldError('gender')) {
echo $this->Form->error('gender');
}
OK, so it doesn't look like there is any built in method to handle what I need which is understandable, so I'm handling it manually by checking the validationErrors for the field.
Here is a cleaner example than the editor_rating field I used perviously:
(artist_picker uses jQuery autocomplete to fetch a list of matching artists. We want to display the artist name in the input, but need to submit the artist_id to the DB, hence updating the hidden field)
echo $this->Form->hidden('artist_id', array('div' => false));
echo $this->Form->input('artist_picker', array(
'label'=> false,
'div'=> (isset($this->validationErrors['Listing']['artist_id']) ? 'span4 error' : 'span4'), // Turn on error class if errors
'class' => (isset($this->validationErrors['Listing']['artist_id']) ? 'span12 form-error' : 'span12'), // Turn on form-error class if errors
'after' => (isset($this->validationErrors['Listing']['artist_id']) ? '<div class="error-message">'.$this->validationErrors['Listing']['artist_id'][0].'</div>' : ''),
'type'=>'text') // Show error message if errors
);

zend framework - group elements of a form within a subforms [duplicate]

I would like to be able to add a hidden form field using array notation to my form. I can do this with HTML like this:
<input type="hidden" name="contacts[]" value="123" />
<input type="hidden" name="contacts[]" value="456" />
When the form gets submitted, the $_POST array will contain the hidden element values grouped as an array:
array(
'contacts' => array(
0 => '123'
1 => '456'
)
)
I can add a hidden element to my form, and specify array notation like this:
$form->addElement('hidden', 'contacts', array('isArray' => true));
Now if I populate that element with an array, I expect that it should store the values as an array, and render the elements as the HTML shown above:
$form->populate($_POST);
However, this does not work. There may be a bug in the version of Zend Framework that I am using. Am I doing this right? What should I do differently? How can I achieve the outcome above? I am willing to create a custom form element if I have to. Just let me know what I need to do.
You have to use subforms to get the result you seek. The documentation was quite a ride but you can find it here
Using what I found there I constructed the following formL
<?php
class Form_Test extends Zend_Form {
public function init() {
$this->setMethod('post');
$this->setIsArray(true);
$this->setSubFormDecorators(array(
'FormElements',
'Fieldset'
));
$subForm = new Zend_Form(array('disableLoadDefaultDecorators' => true));
$subForm->setDecorators(array(
'FormElements',
));
$subForm->addElement('hidden', 'contacts', array(
'isArray' => true,
'value' => '237',
'decorators' => Array(
'ViewHelper',
),
));
$subForm2 = new Zend_Form(array('disableLoadDefaultDecorators' => true));
$subForm2->setDecorators(array(
'FormElements',
));
$subForm2->addElement('hidden', 'contacts', array(
'isArray' => true,
'value' => '456', 'decorators' => Array(
'ViewHelper',
),
));
$this->addSubForm($subForm, 'subform');
$this->addSubForm($subForm2, 'subform2');
$submit = new Zend_Form_Element_Submit('submit');
$submit->setValue('Submit');
$this->addElement('submit', 'submit');
}
}
Wich outputs this html:
<form enctype="application/x-www-form-urlencoded" method="post" action=""><dl class="zend_form">
<input type="hidden" name="contacts[]" value="237" id="contacts">
<input type="hidden" name="contacts[]" value="456" id="contacts">
<dt id="submit-label"> </dt><dd id="submit-element">
<input type="submit" name="submit" id="submit" value="submit"></dd></dl></form>
And when submited the post looks like:
array(2) {
["contacts"] => array(2) {
[0] => string(3) "237"
[1] => string(3) "456"
}
["submit"] => string(6) "submit"
}
So thats how you can create the kind of forms you seek. Hope this helps! if you have a question post a comment!
Its quite hackish if you ask me. You basically create subforms but disable there form decorators so just the element gets output. Since the identical contacts[] elements are in different form object zend does'nt overwrite them and it works. But yeah..
Edit: changed it a bit to remove labels and garbage arount the hidden inputs.
To use array notation, you need to specify that the element "belongs to" a parent array:
$form->addElement('hidden', 'contact123', array('belongsTo' => 'contacts', 'value' => '123'));
$form->addElement('hidden', 'contact456', array('belongsTo' => 'contacts', 'value' => '456'));
This indeed seems to be a bug in Zend Framework - the value attribute for an element is properly set to array, but it's ignored when the element renders - it just uses$this->view->escape($value) to output element's html.
I've solved this by implementing a custom helper for such elements:
class My_View_Helper_HiddenArray extends Zend_View_Helper_FormHidden
{
public function hiddenArray($name, $value = null, array $attribs = null)
{
if (is_array($value)) {
$elementXHTML = '';
// do not give element an id due to the possibility of multiple values
if (isset($attribs) && is_array($attribs) && array_key_exists('id', $attribs)) {
unset($attribs['id']);
}
foreach ($value as $item) {
$elementXHTML .= $this->_hidden($name, $item, $attribs);
}
return $elementXHTML;
} else {
return $this->formHidden($name, $value, $attribs);
}
}
}
Which, when used the next way:
$contacts = $form->createElement('hidden', 'contacts')
->setIsArray(true)
->setDecorators(array(
array('ViewHelper', array('helper' => 'HiddenArray')),
));
$form->addElement($contacts);
generates the needed output.
The reason to extend Zend_View_Helper_FormHidden here is just to be able to call the default behaviour if no array value is set ( return parent::formHidden($name, $value, $attribs) ).
Hope this helps someone :)
For the newer versions of ZF you should use https://framework.zend.com/manual/2.1/en/modules/zend.form.elements.html#multicheckbox

Zend Framework: Working with Form elements in array notation

I would like to be able to add a hidden form field using array notation to my form. I can do this with HTML like this:
<input type="hidden" name="contacts[]" value="123" />
<input type="hidden" name="contacts[]" value="456" />
When the form gets submitted, the $_POST array will contain the hidden element values grouped as an array:
array(
'contacts' => array(
0 => '123'
1 => '456'
)
)
I can add a hidden element to my form, and specify array notation like this:
$form->addElement('hidden', 'contacts', array('isArray' => true));
Now if I populate that element with an array, I expect that it should store the values as an array, and render the elements as the HTML shown above:
$form->populate($_POST);
However, this does not work. There may be a bug in the version of Zend Framework that I am using. Am I doing this right? What should I do differently? How can I achieve the outcome above? I am willing to create a custom form element if I have to. Just let me know what I need to do.
You have to use subforms to get the result you seek. The documentation was quite a ride but you can find it here
Using what I found there I constructed the following formL
<?php
class Form_Test extends Zend_Form {
public function init() {
$this->setMethod('post');
$this->setIsArray(true);
$this->setSubFormDecorators(array(
'FormElements',
'Fieldset'
));
$subForm = new Zend_Form(array('disableLoadDefaultDecorators' => true));
$subForm->setDecorators(array(
'FormElements',
));
$subForm->addElement('hidden', 'contacts', array(
'isArray' => true,
'value' => '237',
'decorators' => Array(
'ViewHelper',
),
));
$subForm2 = new Zend_Form(array('disableLoadDefaultDecorators' => true));
$subForm2->setDecorators(array(
'FormElements',
));
$subForm2->addElement('hidden', 'contacts', array(
'isArray' => true,
'value' => '456', 'decorators' => Array(
'ViewHelper',
),
));
$this->addSubForm($subForm, 'subform');
$this->addSubForm($subForm2, 'subform2');
$submit = new Zend_Form_Element_Submit('submit');
$submit->setValue('Submit');
$this->addElement('submit', 'submit');
}
}
Wich outputs this html:
<form enctype="application/x-www-form-urlencoded" method="post" action=""><dl class="zend_form">
<input type="hidden" name="contacts[]" value="237" id="contacts">
<input type="hidden" name="contacts[]" value="456" id="contacts">
<dt id="submit-label"> </dt><dd id="submit-element">
<input type="submit" name="submit" id="submit" value="submit"></dd></dl></form>
And when submited the post looks like:
array(2) {
["contacts"] => array(2) {
[0] => string(3) "237"
[1] => string(3) "456"
}
["submit"] => string(6) "submit"
}
So thats how you can create the kind of forms you seek. Hope this helps! if you have a question post a comment!
Its quite hackish if you ask me. You basically create subforms but disable there form decorators so just the element gets output. Since the identical contacts[] elements are in different form object zend does'nt overwrite them and it works. But yeah..
Edit: changed it a bit to remove labels and garbage arount the hidden inputs.
To use array notation, you need to specify that the element "belongs to" a parent array:
$form->addElement('hidden', 'contact123', array('belongsTo' => 'contacts', 'value' => '123'));
$form->addElement('hidden', 'contact456', array('belongsTo' => 'contacts', 'value' => '456'));
This indeed seems to be a bug in Zend Framework - the value attribute for an element is properly set to array, but it's ignored when the element renders - it just uses$this->view->escape($value) to output element's html.
I've solved this by implementing a custom helper for such elements:
class My_View_Helper_HiddenArray extends Zend_View_Helper_FormHidden
{
public function hiddenArray($name, $value = null, array $attribs = null)
{
if (is_array($value)) {
$elementXHTML = '';
// do not give element an id due to the possibility of multiple values
if (isset($attribs) && is_array($attribs) && array_key_exists('id', $attribs)) {
unset($attribs['id']);
}
foreach ($value as $item) {
$elementXHTML .= $this->_hidden($name, $item, $attribs);
}
return $elementXHTML;
} else {
return $this->formHidden($name, $value, $attribs);
}
}
}
Which, when used the next way:
$contacts = $form->createElement('hidden', 'contacts')
->setIsArray(true)
->setDecorators(array(
array('ViewHelper', array('helper' => 'HiddenArray')),
));
$form->addElement($contacts);
generates the needed output.
The reason to extend Zend_View_Helper_FormHidden here is just to be able to call the default behaviour if no array value is set ( return parent::formHidden($name, $value, $attribs) ).
Hope this helps someone :)
For the newer versions of ZF you should use https://framework.zend.com/manual/2.1/en/modules/zend.form.elements.html#multicheckbox