Jump to content

FrontendForms - A module for creating and validating forms on the frontend


Recommended Posts

  • 3 weeks later...
Posted (edited)

Version 2.1.19 contains changes to make the module compatible with PHP 8.2 and following versions.

All dynamically created properties have been removed and replaced by a declared property which hold all the properties inside an array. The reason for this is that dynamicalle created properties will be depreciated in 8.2 (leads to a warning) and the will be forbidden in upcoming PHP 9.

So, this was a change affecting a huge amount of files. So please test it carefully and report any issues directly on GitHub.


Due to a writing mistake, there are wrong values inside the database: These wrong values will not be overwritten during the update. It is recommended to uninstall and reinstall the module after the update to be sure that the correct values are stored inside the database. Otherwise it is most likely that you will get an error after a form submission.

Just to mention: the error is in the fieldname of the custom messages: instead of the field name "input_alertErrorText" and "input_alertSuccessText" I have written "input_input_alertSuccessText" and "input_input_alertErrorText". This causes an error after form submission.

Thanks a lot!


Edited by Juergen
Important note
  • Like 2
Link to comment
Share on other sites

Hello Juergen,

So far I've not found a way to have the below behaviour for the filed description.

How can I have the field description for the input tag inside the field (using the placeholder option in the example below

<input type="text" name="event-registration-first-name" id="event-registration-first-name" class="form-control required" value="" placeholder="Enter your First Name">

which get's rendered as 






Link to comment
Share on other sites

Hello @xweb

The placeholder is an attribute and you can add every attribute with the setAttribute() method described here.

$yourField->setAttribute('placeholder', 'Enter your first name');

// or with translatable strings 

$yourField->setAttribute('placeholder', _('Enter your first name'));

Replace $yourField with the variable name of your field object and your done 😀!

You can do this in the same way for every attribute (class, data-attribute, id, rel,.....).

Have a nice day!


  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

Hi Jürgen

I was configuring the module, and after turning asterisks off, I got this:

Fatal Error: Uncaught TypeError: Cannot assign string to property FrontendForms\Label::$enableAsterisk of type int in site/modules/FrontendForms/Formelements/Textelements/Label.php:30

#0 site/modules/FrontendForms/Formelements/Inputelements/Inputfields.php (53): FrontendForms\Label->__construct()
#1 site/modules/FrontendForms/Formelements/Inputelements/Inputs/Input.php (26): FrontendForms\Inputfields->__construct('captcha')
#2 site/modules/FrontendForms/Formelements/Inputelements/Inputs/InputRadioMultiple.php (34): FrontendForms\Input->__construct('captcha')
#3 site/modules/FrontendForms/Formelements/Captcha/AbstractImageCaptcha.php (32): FrontendForms\InputRadioMultiple->__construct('captcha')
#4 site/modules/FrontendForms/Formelements/Captcha/variants/DefaultImageCaptcha.php (27): FrontendForms\AbstractImageCaptcha->__construct()
#5 site/modules/FrontendForms/FrontendForms.module (1686): FrontendForms\DefaultImageCaptcha->__construct()
#6 wire/core/Modules.php (4112): FrontendForms->getModuleConfigInputfields(Object(InputfieldWrapper))
#7 wire/core/Wire.php (419): Modules->___getModuleConfigInputfields('FrontendForms', Object(InputfieldForm))
#8 wire/core/WireHooks.php (952): Wire->_callMethod('___getModuleCon...', Array)
#9 wire/core/Wire.php (484): WireHooks->runHooks(Object(Modules), 'getModuleConfig...', Array)
#10 wire/modules/Process/ProcessModule/ProcessModule.module (1680): Wire->__call('getModuleConfig...', Array)
#11 wire/modules/Process/ProcessModule/ProcessModule.module (1415): ProcessModule->renderEdit('FrontendForms', Array)
#12 wire/core/Wire.php (413): ProcessModule->___executeEdit()
#13 wire/core/WireHooks.php (952): Wire->_callMethod('___executeEdit', Array)
#14 wire/core/Wire.php (484): WireHooks->runHooks(Object(ProcessModule), 'executeEdit', Array)
#15 wire/core/ProcessController.php (350): Wire->__call('executeEdit', Array)
#16 wire/core/Wire.php (413): ProcessController->___execute()
#17 wire/core/WireHooks.php (952): Wire->_callMethod('___execute', Array)
#18 wire/core/Wire.php (484): WireHooks->runHooks(Object(ProcessController), 'execute', Array)
#19 wire/core/admin.php (160): Wire->__call('execute', Array)
#20 wire/modules/AdminTheme/AdminThemeDefault/controller.php (13): require('/customers/a/0/...')
#21 site/templates/admin.php (15): require('/customers/a/0/...')
#22 wire/core/TemplateFile.php (328): require('/customers/a/0/...')
#23 wire/core/Wire.php (413): TemplateFile->___render()
#24 wire/core/WireHooks.php (952): Wire->_callMethod('___render', Array)
#25 wire/core/Wire.php (484): WireHooks->runHooks(Object(TemplateFile), 'render', Array)
#26 wire/modules/PageRender.module (575): Wire->__call('render', Array)
#27 wire/core/Wire.php (416): PageRender->___renderPage(Object(HookEvent))
#28 wire/core/WireHooks.php (952): Wire->_callMethod('___renderPage', Array)
#29 wire/core/Wire.php (484): WireHooks->runHooks(Object(PageRender), 'renderPage', Array)
#30 wire/core/WireHooks.php (1060): Wire->__call('renderPage', Array)
#31 wire/core/Wire.php (484): WireHooks->runHooks(Object(Page), 'render', Array)
#32 wire/modules/Process/ProcessPageView.module (184): Wire->__call('render', Array)
#33 wire/modules/Process/ProcessPageView.module (114): ProcessPageView->renderPage(Object(Page), Object(PagesRequest))
#34 wire/core/Wire.php (416): ProcessPageView->___execute(true)
#35 wire/core/WireHooks.php (952): Wire->_callMethod('___execute', Array)
#36 wire/core/Wire.php (484): WireHooks->runHooks(Object(ProcessPageView), 'execute', Array)
#37 index.php (55): Wire->__call('execute', Array)
#38 {main}
thrown (line 30 of site/modules/FrontendForms/Formelements/Textelements/Label.php) 

This error message was shown because: you are logged in as a Superuser. Error has been logged.

… and I can no longer edit the module settings. What do I do?

Link to comment
Share on other sites

Hello Claus,

thank you for reporting the bug - it is fixed now. There was a missing typehint declaration at the label file.

I have updated the module now to 2.1.26 - alternatively please replace the folllowing file: https://github.com/juergenweb/FrontendForms/blob/main/Formelements/Textelements/Label.php

On line 20 I have changed the following:

protected int $enableAsterisk = 1;

// to

protected int|string $enableAsterisk = 1;

Best regards Jürgen

  • Like 1
Link to comment
Share on other sites

Thank you very much Jürgen. And if I may ask, since I know no PHP, how do I put the submitters name, email, and body into the body of the sent email? In my naïvety I tried 

$m->body($form->getValue('name', 'email', 'message'));

Which just gives me the name.

Link to comment
Share on other sites

Ok, Claus! You are close to the solution.🙂 You will get every value by its name attribute. To add all of them to the body, I recommend you concatenate all the values in one string. 

$email = $form->getValue('email');
$message = $form->getValue('message');

If you have all of your $_POST values than you create your body string (fe with a little HTML markup).

$body = '<ul><li>Email: '.$email.'</li><li>Message: '.$message.'</li></ul>;

As the last step, add it to the mail body:


// or if you want to use HTML markup


You will find a working example at https://github.com/juergenweb/FrontendForms/blob/main/Examples/contactform.php

Best regards

PS: If you will need help, please post the code of your form here.

  • Like 2
Link to comment
Share on other sites

  • 1 month later...

Hi @Juergen

Thanks for this module. I can see that a great and good job has been sold.

The main problem why I still use custom forms is the date picker.
The first problem is to set the range of acceptable times to specify. The second is to inform the user of a date error if the range is still not respected. You do realize that both POST and GET are not perfect.
The other case is when the user needs to specify a range of a start date and an end date. There are more error options here.
There is also a variant when dates are linked. For example, after specifying the first date, the second date can be as much as two weeks later.
Usually such collisions are solved with jQuery.

I looked at your module documentation and didn't see any examples with dates. Maybe you have a similar functionality, but I would like to see an example. 

  • Thanks 1
Link to comment
Share on other sites

Hello @Andy

Thanks for your input on date fields. To be honest, I have not focused on date fields, because I did not use them a lot, but you have inspired me to enhance them.

At the moment, only these 4 date validations can be performed:

  • date - Field is a valid date
  • dateFormat - Field is a valid date in the given format
  • dateBefore - Field is a valid date and is before the given date
  • dateAfter - Field is a valid date and is after the given date

You will find examples of these validations at https://github.com/juergenweb/FrontendForms/blob/main/Examples/field-validation.php#L210

I will take a look of what can be implemented of your suggestions.

To sum it up once more.:

  • You will need to set a time range on a date field, where dates in between are allowed, others are forbidden
  • You will need a validator, that checks if the date entered in a second date field, is inside a specific time range depending on the date entered inside the first field

To the first point, I guess I can write a new method, so you will be able to set the range ( fe $field->setRange('15-05-23', '15-06-23')) or something like this, where first parameter ist the start and the second parameter, the end point of the time range.

To the first point: you can set a time range with dateBefore and dateAfter validators:

$inputDate = new \FrontendForms\InputDate('date');
$inputDate->setLabel('Input Date');
// add the time range between 01-05-2023 and 30-06-2023
$inputDate->setRule('dateBefore', '2023-07-01');

For the second issue I guess I have to write a new custom validator, which takes care of the date in the first field.

I will take a look what I can do :-)

  • Thanks 1
Link to comment
Share on other sites


I wish I had gotten to this part of the documentation. 
The examples always help me.
There are some good choices here.

By the way, the documentation is very well written.

  • Thanks 1
Link to comment
Share on other sites

Hello @Andy

Please update to FrontendForms 2.1.37

I have added 4 new validation rules for dates:

  • dateBeforeField validator: Checks if a date is before a date entered in another field inside the form
  • dateAfterField validator: Checks if a date is after a date entered in another field inside the form
  • dateWithinDaysRange validator: Checks if a date is within a given time range in days depending on a date entered inside another field inside the form. Fe date must be in a time range of 7 days in the future starting from a date entered inside another form field. Example of time range: start date: 2023-05-15, timerange: 2023-05-15 - 2023-05-22. Value must be inside this time range. Supports a positive (future) and negative (past) days value.
  • dateOutsideOfDaysRange validator: Checks if a date is outside a given time range in days depending on a date entered inside another field inside the form. Fe date must after the end of a time range of 7 days starting from a date entered inside another form field. Example of time range: start date: 2023-05-15, forbidden timerange: 2023-05-15 - 2023-05-22. Value must be outside this time range -> after 2023-05-22. Supports a positive (future) and negative (past) days value.

You will find the explanations on how to use here: https://github.com/juergenweb/FrontendForms/tree/main#datebeforefield

The complete examples on how to use them on inputfields can be found inside the examples folder: https://github.com/juergenweb/FrontendForms/blob/main/Examples/field-validation.php#L221

This is full PHP validation - no JS or JQuery. Just to mention: HTML 5 validation does not work for these validation rules. HTML5 validation have to implemented via JS - maybe I will add this in the future, but not for now.

Just take a look if this solves your problem.

Best regards

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Version 2.1.38:

This version now supports HTML5 validation for the 4 new validators added in 2.1.37 by using Javascript. It works by adding min and/or max attribute on the fly to the appropriate input field, if a value has been changed inside the reference field.

Please read the full changelog here for more detailed information.

  • Like 2
Link to comment
Share on other sites

Thank you for making this. Forms being locked behind a paid module was an issue for me so I'm glad this exists.

Can we choose a different directory for a custom email template? I created a custom one in site/modules/FrontendForms/email_templates/ but when I updated the module from the ProcessWire backup, the template file was removed.

I'd love to store the email template in site/templates/

Link to comment
Share on other sites

Hello Martin and welcome!!

Thanks for your report. Your custom templates should not be touched during an update. That was not the plan. At the moment there should not exist a method to add a custom folder. I will try to find a solution to keep custom files untouched without using a custom folder.

At the moment please always make a backup of your custom template and I will try to add a solution to the next update.

Best regards Jürgen

Link to comment
Share on other sites

New version 2.1.39

According to the issue reported by @Martin M there was a problem using custom email templates, which were deleted during the update. This problem is now solved.

Custom templates can be added to a new folder called "frontendforms-custom-templates" which will be created in "site/frontendforms-custom-templates/"

Important: People who are updating (not on a fresh install) have to do the following to create the new folder for the custom templates:


IMPORTANT: The folder will only be created after you have have downloaded the new version of the module and have pressed the "Continue to module settings" button. Pressing of the button forces ProcessWire to create the directory. After that you can put your custom email templates into this folder and select them inside the module configuration. If you install FrontendForms for the first time, the folder will be automatically created during the install process and you have to do nothing special.

If you do not see the template inside the module configuration, please refresh the configuration page after the update.

Please read the full changelog here.

Link to comment
Share on other sites

I finally got to try out the new method for custom templates. It seems that it finds the template (no warning when submitting the form that it can't find it, $mail->send() is successful), but the part that loads the template doesn't check the custom templates directory. In fact this error goes to the email recipient:

Warning: include(/var/www/pw/site/modules/FrontendForms/email_templates/email_template.html): Failed to open stream: No such file or directory in /var/www/pw/site/modules/FrontendForms/Formelements/Form.php on line 444

Warning: include(): Failed opening '/var/www/pw/site/modules/FrontendForms/email_templates/email_template.html' for inclusion (include_path='.:/usr/share/php') in /var/www/pw/site/modules/FrontendForms/Formelements/Form.php on line 444


Link to comment
Share on other sites

Hello @Martin M

Thanks for another issue report - this will help me a lot to make this module more stable! 🙂

I have bumped up the version to 2.1.40 and this version includes an additional check for templates inside the custom template folder.

It first checks if the given template exists inside the default folder. If not then it checks for the template inside the custom folder and if the template is not found there it will throw an exception.

But you were right, there was a missing link to the custom folder inside the function the loads the template.👍

16 hours ago, Martin M said:

In fact this error goes to the email recipient:

This is what I cannot reproduce, because I have included a check before if the mail template exists and if not it should thrown an exception.

In my case this check works and outputs the error message and the email will not be sent.


Anyway, I have made an additional check inside the form.php. You can take a look at the changes here.

Please download the latest version and let me know if it solves the problem in your case.

Best regards Jürgen

Link to comment
Share on other sites

New version 2.1.41

This version comes with 2 minor updates:

- To prevent warning of depreciated dynamically declared properties if you are running PHP 8.2, 2 properties inside AbstractImageCaptcha.php will be re-written to static properties.

- The second change improves the UI inside the fieldset for the "Statistics of blocked visitors":

The statistic of blocked visitiors will only be created if logging of failed attempts is enabled. By default this is turned off, so the user sees the following message inside this fieldset.


This only informs the user that there are no entries inside the log files of the failed attempts, but it does not inform the user that logging is disabled by default. If logging of failed attempts is never enabled, you will always get this message and no entries/statistics.

To make this more clearer for the user, I have decided to add an additional message, which informs the user, that logging of failed attempts is not enabled.


At the bottom you will find a link ('Go to the settings to enable logging of failed attempts'). If you click on that link, the appropriate fieldset for changing the settings for logging failed attempts will be openend automatically and you can make your changes. This will be done via the help of a little JavaScript.


So this is just a minor improvement, but it is more userfriendly than before, because it helps the user to take the necessary steps to enable logging.

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

Hi @Juergen is there a way to mimic setDefaultValue() for images fields?
I would like to use your module for editing existing pages in frontend and it would be great to be able to edit and delete existing images and add new ones.

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Create New...