Trying to use a DateTime Form element in ZF2 and cannot valid the form.
$inputFilter->add(array(
'name' => 'event_datetime',
'required' => true,
'filters' => array(
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 0,
'max' => 20,
),
),
),
));
Using this on the .phtml file.
<?php $formElement = $form->get('event_datetime');?>
<dt><?php echo $this->formLabel($formElement);?></dt>
<dd><?php echo $this->formDateTimeLocal($formElement);?>
<?php echo $this->formElementErrors($formElement);?>
NOTE: using formDateTimeLocal instead of formDateTime as the latter does not show the HTML5 elements.
Using Chrome the HTML5 DateTimeLocal field appears with a calendar and Time section.
When running $form->isValid() I receive: (var_dump($form->getMessages()))
array (size=1) 'event_datetime' => array (size=1) 'dateInvalidDate' => string 'The input does not appear to be a valid date' (length=44)
The getRequest->getPost() = public 'event_datetime' => string '2015-08-10T03:00' (length=16)
I've tried to split this field into 2: a Date and a Time field as separate variables. This works correctly for the Date BUT not for the Time element.
Reading around I've noticed this: ZF2 validating date and time format PT_BR always The input does not appear to be a valid date which does not help as I need the time component. (obviously I have looked at more than just 1 link but my rep on SO allows only 1 url in post.)
I've also read that Chrome and Opera cut off the 'seconds' part of the time field....
How to I validate either a \Zend\Form\Element\DateTime field or just the \Zend\Form\Element\Time for field...
I've tried to manually glue these together, add the :00 seconds part of the string to Time but to no effect.
If I set the input filter to 'required' => false I still receive the dateInvalidDate validator for for attempts: DateTime and Time...
So, the question is:
How do I validate a DateTime or Time field using Zf2 form elements and inputFilters. Following the Docs and example don't seem to work for me and manually creating the Time string also has the same issue.
Try this:
$inputFilter->add(array(
'type' => 'Zend\Form\Element\DateTimeLocal',
'name' => 'event_datetime',
'required' => true,
'options' => array(
'label' => 'Appointment Date',
'format' => 'Y-m-d\TH:i'
),
'filters' => array(
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 0,
'max' => 20,
),
),
),
));
You get the error, because the datetime string/format you pass is different than the expected datetime format by default. Try playing with 'format' => 'Y-m-d\TH:i' to get the result.
Taken directly from Zend documentation. It's all the same, but with a different element.
use Zend\Form\Element;
use Zend\Form\Form;
$time = new Element\Time('time');
$time
->setLabel('Time')
->setAttributes(array(
'min' => '00:00:00',
'max' => '23:59:59',
'step' => '60', // seconds; default step interval is 60 seconds
))
->setOptions(array(
'format' => 'H:i:s'
));
$form = new Form('my-form');
$form->add($time);
My original issue was validation. The suggestion by Stanimir did help and the dateTimeLocal format has great in pointing me in the right direction.
The whole issue was with the 'format' value.
My main problem was that when populating the \Zend\Form\Element\Time field the format was H:i:s but the HTML5 form only submitted H:i. (also due to my 'format' setting which is OK)
So, when populating the form the DB field returned H:i:s which populated the form correctly BUT on submission failed IF I didn't edit the Time field.
THEREFORE: the answer to this questions is basically make sure the format submitted [and $form->bind($object), $form->setData($post) etc] is EXACTLY the same as the form element definition [H:i != H:i:s] and when pulling from database format to correspond to your required setting.
var_dump($form->get('valid_to_time')->getFormat());
var_dump($form->get('valid_to_time')->getValue());
Once this is the same all will be well and you can split DateTime fields into individual Date and Time (or use DateTime as above).
Sounds simple but this was a headache to get right.
Related
$inputFilter->add(array(
'name' => 'seatingCapacity',
'required' => TRUE,
'filters' => array(
array('name' => 'Int'),
),
));
In my Doctrine Entity, I have a getInputFilter method which I use for form validation. The above is code snippet for one of the input elements. My problem is the required => true is not working even if I submit an empty form.
After researching I found out, that the Int filter converts the empty input to 0 and submits it and that is why the required validator is not working. I just need reasons why it may not be working.
For reference where I searched
Zend Framework 2 - Integer Form Validation
where he suggests to use Between validator
$inputFilter->add($factory->createInput(array(
'name' => 'zip',
'required' => true,
'filters' => array(
array('name' => 'Int'),
),
'validators' => array(
array(
'name' => 'Between',
'options' => array(
'min' => 1,
'max' => 1000,
)
)
)
)
));
I want to know why I should use Between and why required is failing.
You should only use the Between validator to validate if the given value is Between a min and max value. It has nothing to do with solving your empty value to 0 issue.
You should ask yourself 2 questions:
Is 0 a valid value?
Do I want to automatically cast null empty string ('') and other empty values to this 0 or not?
If you actually want to prevent that the Int filter sets an empty value to 0, maybe then you should not use this filter at all then?
You can instead add an IsInt validator to check if the given value is an integer. Your required => true setting will work as expected and validation will fail on any other (not integer) input so also on null, empty strings etc.
Thank you for your time, energy & effort.
Actually I solved the problem.
I had copy-pasted the code, which I should have been careful while doing so.
What I found out is there is no such filter named 'Int' and actually it's 'Digits'
$inputFilter->add(array(
'name' => 'seatingCapacity',
'required' => TRUE,
'filters' => array(
array('name' => 'Int'),
),
));
shows me error because the filter name should have been 'Digits'.
Only doing so solved my problem and works as per my requirement.
$inputFilter->add(array(
'name' => 'seatingCapacity',
'required' => TRUE,
'filters' => array(
array('name' => 'Digits'),
),
));
This is the right way to do and I would advice you to be careful while referring code from your sources because it's an illogical mistake I did.
Happy coding
I've encoutered problem with filtering pages to display in WP query.
I use Codex WP query reference for custom fields with ACF (Advanced Custom Fields plugin - but it doesn't matter, couse it works same as WP custom field) parameters to filter pages.
In "Multiple Custom Field Handling" paragraph, Codex got an example with 2 conditions. We can use OR or AND relation. I works for both until you have 3rd condition (array).
They use example:
'relation' => 'OR',
array(
'key' => 'color',
'value' => 'blue',
'compare' => 'NOT LIKE'
),
array(
'key' => 'price',
'value' => array( 20, 100 ),
'type' => 'numeric',
'compare' => 'BETWEEN'
)
It has only 2 arrays. When I put 3rd, nothing shows. In debug mode I can see an error:
WordPress database error: [Lost connection to MySQL server during query]
When I use AND it works, but I got to use OR. Unfortunately it makes MySQL disconnect.
I've tryed asking phpMySQL for same query WP does. It couses problem - phpMyAdmin says same:
Lost connection
Any Idea?
Maybe I should try different aproach for filtering? (maybe I should use taxonomy?)
Here is code I use:
$query_array = array('relation' => 'OR');
array_push($query_array,
array(
'key' => 'filter1',
'value' => 'value1',
'compare' => 'LIKE'
),
array(
'key' => 'filter1',
'value' => 'value2',
'compare' => 'LIKE'
),
array(
'key' => 'filter1',
'value' => 'value3',
'compare' => 'LIKE'
)
);
$args = array(
'order' => $order_array,
'meta_key' => $meta_key,
'orderby' => $orderby,
'post_type' => 'page',
'paged' => $paged,
'post__in' => $postIDs,
'posts_per_page' => 12,
'paged' => get_query_var('paged'),
'meta_query' => $query_array
);
query_posts($args);
?>
(variables for $args are set of course)
I don't know why I can't use
'compare' => '='
but probably it is why I can't use:
$query_array = array('relation' => 'OR');
array_push($query_array,
array(
'key' => 'filter1',
'value' => array('value1', 'value2', 'value3'),
'compare' => 'IN'
)
);
Just wanted to say that your comment helped me; I'd been butting my head against a very similar problem for a while. I'm using ACF too, and using it to attach items of one post type to another custom post type was easy - for instance, to Attach Person_1 and Person_3 to "Project_A".
This made it easy to list out which users were attached to specific projects. But when it came to do the same in reverse - to show which projects were attached to which users - it became a massive headache.
I finally figured it out, in part thanks to your comment - I'll post my solution here in case someone else comes along with the same problem:
$args = array(
'numberposts' => -1,
'post_type' => 'project',
'meta_query' => array(
'relation' => 'IN',
array(
'key' => 'people',
'value' => ';s:1:"' . $person->ID . '";',
'compare' => 'LIKE'
)
)
);
In short: because the ACF values in repeater fields et cetera are serialized, the compare keyword has to be "LIKE", and I added some context to the value to eliminate false returns - just searching for an ID like "1" would match a lot of the (wrong) posts, but the ";s1;" part ensures that the given value is at index 1, which in my case is the correct index.
So it would need tweaking from case to case. Inspecting what you're trying to match up with var_dumping "get_post_meta($post->ID, 'people')" is helpful for getting the value correct.
I am brand new to Zend and I've been given a project to make adjustments on. I'd like to add html to the labels for my form elements but I can't seem to get it right.
Here's what I have:
$this->addElement('text', 'school_name', array(
'filters' => array('StringTrim'),
'validators' => array(
array('StringLength', false, array(0, 150)),
),
'required' => true,
'label' => 'Name* :<img src="picture.png">,
'size' => '90',
));
As is, of course, the <img src="picture.png"> text gets escaped and the whole string is displayed.
I've read that I need to use 'escape' => false in some capacity but I can't figure out where/how to use it in my specific case.
Any help would be great. Thanks!
After calling addElement fetch the label's decorator and change the escape setting:
$form->getElement('school_name')->getDecorator('label')->setOption('escape', false);
If you use this type of label a lot, you should consider writing a custom decorator.
You can also use the disable_html_escape in 'label_options' when adding an element to the form:
$this->add(array(
....
'options' => array(
'label' => '<span class="required">Name</span>,
'label_options' => array(
'disable_html_escape' => true,
)
),
...
));
Credit to Théo Bouveret's post 'Button content in ZF2 forms' for the answer.
I have a form with 2 selects. Based on the value of the first select, it updates the values of the second select using AJAX. Doing this makes the form not being valid. So, I made the next change:
$form=$this->getAddTaskForm(); //the form
if(!$form->isValid($_POST)) {
$values=$form->getValues();
//get the options and put them in $options
$assignMilestone=$form->getElement('assignedMilestone');
$assignMilestone->addMultiOptions($options);
}
if($form->isValid($_POST)) {
//save in the database
}else {
//redisplay the form
}
Basically, I check if it is valid and it isn't if the user changed the value of the first select. I get the options that populated the second select and populate the form with them. Then I try to validate it again. However this doesn't work. Anybody can explain why? The same "value was not found in the haystack" is present.
You could try to deactivate the validator:
in your Form.php
$field = $this->createElement('select', 'fieldname');
$field->setLabel('Second SELECT');
$field->setRegisterInArrayValidator(false);
$this->addElement($field);
The third line will deactivate the validator and it should work.
You can also disable the InArray validator using 'disable_inarray_validator' => true:
For example:
$this->add( array(
'name' => 'progressStatus',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'options' => array(
'disable_inarray_validator' => true,
),
));
Additionaly you should add you own InArray Validator in order to protect your db etc.
In Zend Framework 1 it looks like this:
$this->addElement('select', $name, array(
'required' => true,
'label' => 'Choose sth:',
'filters' => array('StringTrim', 'StripTags'),
'multiOptions' => $nestedArrayOptions,
'validators' => array(
array(
'InArray', true, array(
'haystack' => $flatArrayOptionsKeys,
'messages' => array(
Zend_Validate_InArray::NOT_IN_ARRAY => "Value not found"
)
)
)
)
));
Where $nestedArrayOptions is you multiOptions and $flatArrayOptionsKeys contains you all keys.
You may also add options to select element before checking for the form validation. This way you are insured the select value is in range.
I am using CakePHP 1.3 to create a select menu for date of birth (as below). I can set the default starting values as either blank or a selected date, but ideally I would like to have DD-MM-YYYY as the starting displayed values:
echo $form->input('dob',
array(
'before' => '',
'between' => '',
'after' => '',
'label' => false,
'divider' => false,
'monthNames' => false,
'selected' => false,
'empty' => true,
'dateFormat' => 'DMY',
'minYear' => date('Y') - 70,
'maxYear' => date('Y') - 16,
'error' => array('wrap' => 'div', 'class' => 'error-copy')
));
What I get:
What I would like:
Thank you
I believe if you want to do this you will have to make your own date fields and not use the FormHelper since you can only set a default date to it, what you want involves adding an element to the fields.
You could also try JQuery's datepicker out, it's what I use in my project, and since it's a text field you can just set whatever you want as a placeholder.
http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#options-for-select-checkbox-and-radio-inputs
echo $this->Form->dateTime('Contact.date', 'DMY', '12',
array(
'empty' => array(
'day' => 'DAY', 'month' => 'MONTH', 'year' => 'YEAR',
'hour' => 'HOUR', 'minute' => 'MINUTE', 'meridian' => false
)
)
);
I believe you can only set a default date on the date fields.
echo $this->Form->input('close_time', array('type' => 'time', 'selected' => '13:30:00'));
Cookbook entry
For the benefit of anyone Googling to find the answer to this question 1+ years after it was asked, we can now simply do the following to set default placeholder (temporary) values in CakePHP forms that are easily replaced when clicked:
<?php echo $this->Form->input('Email', array(
'placeholder'=>'Enter Your Email Here'
)); ?>
I like to include 'label' => false as well to make the forms really minimalist.