Jump to content

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


Juergen

Recommended Posts

Version 2.2.0 is out!

This version is a bigger update, so I have decided to change the version number from 2.1.xx to 2.2.

Whats new?

This version includes a new admin module called "FrontendForms Manager", which is an easy to use UI for entering as many questions as you want for the "Simple question CAPTCHA".

At the moment this module is only for entering questions, but I have plans for the future to expand the functionality. That is the reason why I do not call it only "Question Manager" or something like that.

The "Simple question CAPTCHA" is a CAPTCHA type that I have added not so long ago and it forces the user to answer a simple question before submitting the form.

You will find a live example using this new module with the simple question CAPTCHA here: https://www.schulfreund.at/kontakt/

Unfortunately, this page is only in German, but you will get the idea how it works ?

I have not so much real life experience with this CAPTCHA type, but @Andi from the forum uses this type of CAPTCHA very heavily and he had no problems with SPAM until now. So if you have troubles with SPAM, give this CAPTCHA type a chance to be your friend ?!

The only disadvantage of this CAPTCHA type is, that you have to create your questions first. But the big advantage is that you can adopt the questions to your customer, so that the CAPTCHA has a more personal touch.

frontendformsmanager.thumb.png.1de83b2da3880215b9ff15b8d539f7a0.png

The usage of this module is optional, so it will not be installed automatically during the update. You will need to got the module manager and install it like all other modules. I do not want to go to much into detail, because I have written a description of the FrontendForms Manager in the Readme file on Github. There you can find also more images about the Userinterface. So take a look there to get more information about it.

Here is only a brief description about the funcionality of this module:

  • Creates a new admin page under Setup called "FrontendForms Manager"
  • After clicking the link you will be redirected to the "Dashboard"
  • The Dashboard page contains some statistical data about the questions and a little statistical section with charts
  • By clicking on a button on the "Dashboard page" you will be redirected to the next page which contains all questions inside a table (a kind of questions overview page)
  • There you can select if you want to edit/delete or to add a new question
  • Depending on your choice you will be redirected to an "edit" or "add new" page where you can enter the several data for the question
  • Each question is highly customizable, which means that you can enter notes, description, error message, success message etc. individually for each question

As always, this is a brand new module, so it is not recommended to try it out on a live site first. I have run several tests without problems, but I cannot cover all possible scenarios.

If you discover any problems, please report it here or directly on GitHub.

Special thanks goes to @bernhard for writing a fantastic tutorial on "How to create custom admin pages". This tutorial helped me a lot during the development of this module.

Jürgen

  • Like 6
Link to comment
Share on other sites

Thanks for this awesome module!! I am running it on various installations without any issues and flaws! ?

Now, a client wants to show form fields only, if the user selected one check box. In the file, I am calling InputRadioMultiple to integrate various buttons. How to I validate for one specific button being checked to show additional form fields?

Happy for any input. Thanks a lot!!!

  • Like 1
Link to comment
Share on other sites

Hello @mjut

Just to clearify:

You have created a form and inside this form there is a radio multiple inputfield with, lets say 3 radio buttons (A,B,C). If the user clicks on radio button A, then some form fields will be displayed (added) to the form. If the user clicks on radio button B, then other form fields will be displayed (added).

At the end the user submits the form and it should be validated. Is this the correct scenario that you want to achive? Can you post the form code, that you have so far?

Link to comment
Share on other sites

$contacttype = new \FrontendForms\InputRadioMultiple('auswahl');
$contacttype->addOption('Einzelperson'); // 1 person
$contacttype->addOption('Doppelmitgliedschaft'); // 2 persons
$contacttype->alignVertical();
$contacttype->setRule('required');
$form->add($contacttype);

This is to add the Radio-Buttons to my form. Works perfectly.
After that I add form-fields for name, surname, adress etc.

The working example is living here: https://www.museumsvereincelle.de/der-verein/mitglied-werden/

My idea was to hide certain fields when option 1 is selected (1 Person) and show specific fields when option 2 is selected (2 persons).
(Sorry for the complicated description. As the example is in German... )

 

 

Link to comment
Share on other sites

Ok, I see!

Just to mention: To validate the form (including the hidden fields if they are displayed after clicking a certain radio button) all fields must be added to the form object.

This means: You need  to create ALL form fields first and add them to the form object (independent if the should be visible or not). Now all fields are visible. This is the point were you are now.

To change the visibility of certain form fields, you need Javascript (Jquery or plain JS). Take an eventlistener and check if radio button 1 (Einzelperson) or radio button 2 (Doppelmitgliedschaft) has been clicked. Depending on that you hide or show the fields inside the form.

The second part would be the validation depending on the radio button status. So you need to add a validator which has a dependency on the radio button value selected.

To clearify:

If you want to make some of the fields required, if they are visible, you need to add a required validator with dependency of the value selected in the radio button multiple.

More in detail: Field A is only required if radio button A is selected, Field B is only required if radio button B is selected and so on. So we need a kind of "requiredIf" validator, but I am afraid that Valitron does not offer such a validator. There is only a requiredWith validator and I guess this is not the right one for your usecase, but I have not used it before, so I am not sure

Maybe there is a need to create a custom validator for this scenario.?

30 minutes ago, mjut said:

(Sorry for the complicated description. As the example is in German... )

That does not matter - I am speaking German ?

Can you post the complete form code here, so I can make an exact copy of your form on my local host for testing purposes.  Please also write which form fields should be visible on the first  and wich one on the second radio button.

  • Like 2
Link to comment
Share on other sites

Thank you so much for the detailed answer! I see, there is a lot to learn for me ?

I did use and edited your example from github contactform-2.php:

<?php
		declare(strict_types=1);
		
		namespace ProcessWire;
		
		/*
		 * File description
		 *
		 * Created by Jürgen K.
		 * https://github.com/juergenweb
		 * File name: contactform-2.php
		 * Created: 15.02.2023
		 */
		
	
		$form = new \FrontendForms\Form('contact');
		$form->setMaxAttempts(0); // disable max attempts

		//$contacttype = new \FrontendForms\InputCheckboxMultiple('auswahl');
		$contacttype = new \FrontendForms\InputRadioMultiple('auswahl');
		//$contacttype->setNotes('*');
		$contacttype->addOption('Einzelperson (Jahresbeitrag 50,00 EUR)<span class="asterisk">*</span>', 'Einzelperson (Jahresbeitrag 50,00 EUR)');
		$contacttype->addOption('Doppelmitgliedschaft (Jahresbeitrag 75,00 EUR)<span class="asterisk">*</span>', 'Doppelmitgliedschaft (Jahresbeitrag 75,00 EUR)');
		$contacttype->alignVertical();
		$contacttype->setRule('required');
		$form->add($contacttype);
		
		// add the gender field
		$gender = new \FrontendForms\Gender('gender');
		//$gender->setLabel('Auswählen'); // so Label setzen!
		$form->add($gender);
		
		// add the name field
		$name = new \FrontendForms\Name('firstname');
		$form->add($name);
		
		// add the surname field
		$surname = new \FrontendForms\Surname('lastname');
		$form->add($surname);
		
		
		// add the name2 field
		$name2 = new \FrontendForms\InputText('firstname2');
		$name2->setLabel('Vorname (zweite Person)');
		$form->add($name2);
		
		// add the surname2 field
		$surname2 = new \FrontendForms\InputText('lastname2');
		$surname2->setLabel('Nachname (zweite Person)');
		$form->add($surname2);
		
		
		// Adresse
		$adresse = new \FrontendForms\InputText('adresse');
		$adresse->setLabel('Straße und Hausnummer');
		$adresse->setRule('required');
		$form->add($adresse);

		// plz
		$plz = new \FrontendForms\InputText('plz');
		$plz->setLabel('Postleitzahl');
		$plz->setRule('required');
		$form->add($plz);

		// Ort
		$ort = new \FrontendForms\InputText('ort');
		$ort->setLabel('Ort');
		$ort->setRule('required');
		$form->add($ort);

		// add the email field
		$email = new \FrontendForms\Email('email');
		if ($user->isLoggedIn()) {
				$email->setDefaultValue($user->email);
		}
		$form->add($email);
		
		// add the phone field
		$phone = new \FrontendForms\Phone('phone');
		$phone->setLabel('Telefon / Mobil');
		$phone->setRule('required');
		$form->add($phone);
		
		// add the Geburtstags field
		$geb = new \FrontendForms\Phone('geb');
		$geb->setLabel('Geburtsdatum');
		$form->add($geb);		
		
		$einzug = new \FrontendForms\InputCheckbox('einzug');
		$einzug->setLabel('Hiermit ermächtige ich den Museumsverein Celle e.V. widerruflich, die von mir zu entrichtende Beitragszahlung jährlich bei Fälligkeit zu Lasten meines Kontos mittels Lastschrift einzuziehen. Wenn mein Konto die erforderliche Deckung nicht aufweist, besteht seitens des kontoführenden Geldinstituts keine Verpflichtung zur Einlösung.');
		$einzug->setRule('required')->setCustomMessage('Bitte bestätigen Sie die Einzugsermächtigung.');;
		$form->add($einzug);
		
		// Kontoinhaber
		$kontoinhaber = new \FrontendForms\InputText('kontoinhaber');
		$kontoinhaber->setLabel('Kontoinhaber');
		$kontoinhaber->setRule('required');
		$form->add($kontoinhaber);

		// Kreditinstitut
		$kreditinstitut = new \FrontendForms\InputText('kreditinstitut');
		$kreditinstitut->setLabel('Kreditinstitut');
		$kreditinstitut->setRule('required');
		$form->add($kreditinstitut);

		// BIC
		$bic = new \FrontendForms\InputText('bic');
		$bic->setLabel('BIC');
		$bic->setRule('required');
		$form->add($bic);

		// IBAN
		$iban = new \FrontendForms\InputText('iban');
		$iban->setLabel('IBAN');
		$iban->setRule('required');
		$form->add($iban);
				
		// add the privacy field
		$privacy = new \FrontendForms\Privacy('privacy');
		$form->add($privacy);
		
		// add the send copy field
		$sendcopy = new \FrontendForms\SendCopy('sendcopy');
		$form->add($sendcopy);
		
		$button = new \FrontendForms\Button('submit');
		$button->setAttribute('value', 'Absenden');
		$form->add($button);
		
		if ($form->isValid()) {
		
				/** You can grab the values with the getValue() method - this is the default (old) way */
				/*
				$body = $m->title;
				$body .= '<p>Sender: '.$form->getValue('gender').' '. $form->getValue('firstname').' '.$form->getValue('lastname').'</p>';
				$body .= '<p>Mail: '.$form->getValue('email').'</p>';
				$body .= '<p>Subject: '.$form->getValue('subject').'</p>';
				$body .= '<p>Message: '.$form->getValue('message').'</p>';
				*/
		
				/** You can use placeholders for the labels and the values of the form fields
				 * This is the modern new way - only available at version 2.1.9 or higher
				 * Big advantage: You do not have to use PHP code and there are a lot of ready-to-use placeholders containing fe the current date, the domain,.....
				 * But it is up to you, if you want to use placeholders or do it the old way
				 *
				 */
		
				$body = '[[TITLE]]
						[[AUSWAHLVALUE]]<br><br>
						[[GENDERVALUE]]<br>
						[[FIRSTNAMELABEL]]: [[FIRSTNAMEVALUE]]<br>
						[[LASTNAMELABEL]]: [[LASTNAMEVALUE]]<br>
						[[FIRSTNAME2LABEL]]: [[FIRSTNAME2VALUE]]<br>
						[[LASTNAME2LABEL]]: [[LASTNAME2VALUE]]<br>
						[[ADRESSEVALUE]]<br>
						[[PLZVALUE]]&nbsp;
						[[ORTVALUE]]<br>
						[[EMAILVALUE]]<br>
						[[PHONELABEL]]: [[PHONEVALUE]]<br>
						[[GEBLABEL]]: [[GEBVALUE]]<br><br>
						[[KREDITINSTITUTLABEL]]: [[KREDITINSTITUTVALUE]]<br>
						[[KONTOINHABERLABEL]]: [[KONTOINHABERVALUE]]<br>
						[[BICLABEL]]: [[BICVALUE]]<br>
						[[IBANLABEL]]: [[IBANVALUE]]<br><br>
		
				// send the form with WireMail
				$m = wireMail();
		
				if ($form->getValue('sendcopy')) {
						// send copy to sender
						$m->to($form->getValue('email'));
				}
	
				$m->to('mail@mail.de')// please change this email address to your own
				->from($form->getValue('email'))
				->subject('Ein neuer Mitgliedsantrag von ' . $form->getValue('firstname') . ' ' . $form->getValue('lastname'))
				->title('<h1>Neuer Mitgliedsantrag</h1>') // this is a new property from this module
				->bodyHTML($body)
				->sendAttachments($form);
		
				if (!$m->send()) {
						$form->generateEmailSentErrorAlert(); // generates an error message if something went wrong during the sending process
				}
		
		}
		
		$content .= $form->render();
		
		echo $content;

When selecting the option for "Doppelmitgliedschaft" the fields $name2 ('firstname2') and $surname2 ('lastname2') should appear.

 

Link to comment
Share on other sites

10 minutes ago, Juergen said:

Ok, I will try to figure it out. I guess these 2 fields should be required if "Doppelmitgliedschaft" is selected, am I right?

hmmyes. But that would make things even more complicated? (I am not really familar with ajax.)

By the way: its super helpful that you provided the exmple files. very good organised an written. big ups!

  • Like 2
Link to comment
Share on other sites

2 minutes ago, mjut said:

hmmyes. But that would make things even more complicated? (I am not really familar with ajax.)

You do not need Ajax in this case - only JS is enough. I will try to write the JS for showing and hiding the fields and afterwards we will see further for setting the fields to required or not.?

4 minutes ago, mjut said:

By the way: its super helpful that you provided the exmple files. very good organised an written. big ups!

Thanks! I know these docs are just like more a book, so offering examples is often much clearer for the users.

  • Like 3
Link to comment
Share on other sites

Hi, here is the new code for your contact form:

<?php
    declare(strict_types=1);

    namespace ProcessWire;

    /*
     * File description
     *
     * Created by Jürgen K.
     * https://github.com/juergenweb
     * File name: contactform-2.php
     * Created: 15.02.2023
     */

    $content = '';

    $form = new \FrontendForms\Form('contact');
    $form->setMaxAttempts(0); // disable max attempts

    $contacttype = new \FrontendForms\InputRadioMultiple('auswahl');
    $contacttype->addOption('Einzelperson (Jahresbeitrag 50,00 EUR)<span class="asterisk">*</span>', 'Einzelperson (Jahresbeitrag 50,00 EUR)')->setAttribute('data-value', '1');
    $contacttype->addOption('Doppelmitgliedschaft (Jahresbeitrag 75,00 EUR)<span class="asterisk">*</span>', 'Doppelmitgliedschaft (Jahresbeitrag 75,00 EUR)')->setAttribute('data-value', '2');
    $contacttype->alignVertical();
    $contacttype->setRule('required')->setCustomMessage('Bitte wählen Sie die gewünschte Mitgliedschaft aus.');
    $form->add($contacttype);

// add the gender field
    $gender = new \FrontendForms\Gender('gender');
//$gender->setLabel('Auswählen'); // so Label setzen!
    $form->add($gender);

// add the name field
    $name = new \FrontendForms\Name('firstname');
    $name->setRule('firstAndLastname')->setCustomFieldName('Der Vorname');
    $form->add($name);

// add the surname field
    $surname = new \FrontendForms\Surname('lastname');
    $surname->setRule('firstAndLastname')->setCustomFieldName('Der Nachname');
    $form->add($surname);

// check if $_POST value is present for "auswahl" and set "display" according to "auswahl" value
    $display = 'none';
    if (wire('input')->post('contact-auswahl')) {
        $value = explode(' ', wire('input')->post('contact-auswahl'));
        if ($value != 'Einzelperson') {
            $display = 'block';
        }
    }

// add the name2 field
    $name2 = new \FrontendForms\InputText('firstname2');
    $name2->setLabel('Vorname (zweite Person)');
    $name2->setRule('firstAndLastname')->setCustomFieldName('Der Vorname der zweiten Person');
    $name2->useCustomWrapper()->setAttribute('id', 'firstname-wrapper')->setAttribute('style', 'display:' . $display);
    $form->add($name2);

// add the surname2 field
    $surname2 = new \FrontendForms\InputText('lastname2');
    $surname2->setLabel('Nachname (zweite Person)');
    $surname2->setRule('firstAndLastname')->setCustomFieldName('Der Nachname der zweiten Person');
    $surname2->useCustomWrapper()->setAttribute('id', 'lastname-wrapper')->setAttribute('style', 'display:' . $display);
    $form->add($surname2);


// Adresse
    $adresse = new \FrontendForms\InputText('adresse');
    $adresse->setLabel('Straße und Hausnummer');
    $adresse->setRule('required')->setCustomFieldName('Die Adresse');
    $form->add($adresse);

// plz
    $plz = new \FrontendForms\InputText('plz');
    $plz->setLabel('Postleitzahl');
    $plz->setRule('integer')->setCustomFieldName('Die Postleitzahl');
    $plz->setRule('required');
    $form->add($plz);

// Ort
    $ort = new \FrontendForms\InputText('ort');
    $ort->setLabel('Ort');
    $ort->setRule('required')->setCustomFieldName('Der Ort');
    $form->add($ort);

// add the email field
    $email = new \FrontendForms\Email('email');
    if ($user->isLoggedIn()) {
        $email->setDefaultValue($user->email);
    }
    $form->add($email);

// add the phone field
    $phone = new \FrontendForms\Phone('phone');
    $phone->setLabel('Telefon / Mobil');
    $phone->setRule('required')->setCustomFieldName('Die Telefonnummer');
    $form->add($phone);

// add the Geburtstags field
    $geb = new \FrontendForms\InputText('geb');
    $geb->setLabel('Geburtsdatum');
    $form->add($geb);

    $einzug = new \FrontendForms\InputCheckbox('einzug');
    $einzug->setLabel('Hiermit ermächtige ich den Museumsverein Celle e.V. widerruflich, die von mir zu entrichtende Beitragszahlung jährlich bei Fälligkeit zu Lasten meines Kontos mittels Lastschrift einzuziehen. Wenn mein Konto die erforderliche Deckung nicht aufweist, besteht seitens des kontoführenden Geldinstituts keine Verpflichtung zur Einlösung.');
    $einzug->setRule('required')->setCustomMessage('Bitte bestätigen Sie die Einzugsermächtigung.');
    $form->add($einzug);

// Kontoinhaber
    $kontoinhaber = new \FrontendForms\InputText('kontoinhaber');
    $kontoinhaber->setLabel('Kontoinhaber');
    $kontoinhaber->setRule('firstAndLastname')->setCustomFieldName('Der Name des Kontoinhabers');
    $kontoinhaber->setRule('required')->setCustomMessage('Der Name des Kontoinhabers muss ausgefüllt werden.');
    $form->add($kontoinhaber);

// Kreditinstitut
    $kreditinstitut = new \FrontendForms\InputText('kreditinstitut');
    $kreditinstitut->setLabel('Kreditinstitut');
    $kreditinstitut->setRule('required')->setCustomFieldName('Das Kreditinstitut');
    $form->add($kreditinstitut);

// BIC
    $bic = new \FrontendForms\InputText('bic');
    $bic->setLabel('BIC');
    $bic->setRule('required')->setCustomFieldName('Der BIC-Code');
    $form->add($bic);

// IBAN
    $iban = new \FrontendForms\InputText('iban');
    $iban->setLabel('IBAN');
    $iban->setRule('required')->setCustomFieldName('Der IBAN-Code');
    $form->add($iban);

// add the privacy field
    $privacy = new \FrontendForms\Privacy('privacy');
    $form->add($privacy);

// add the send copy field
    $sendcopy = new \FrontendForms\SendCopy('sendcopy');
    $form->add($sendcopy);

    $button = new \FrontendForms\Button('submit');
    $button->setAttribute('value', 'Absenden');
    $form->add($button);

    if ($form->isValid()) {

        /** You can use placeholders for the labels and the values of the form fields
         * This is the modern new way - only available at version 2.1.9 or higher
         * Big advantage: You do not have to use PHP code and there are a lot of ready-to-use placeholders containing fe the current date, the domain,.....
         * But it is up to you, if you want to use placeholders or do it the old way
         *
         */

        $body = '[[TITLE]]
            [[AUSWAHLVALUE]]<br><br>
            [[GENDERVALUE]]<br>
            [[FIRSTNAMELABEL]]: [[FIRSTNAMEVALUE]]<br>
            [[LASTNAMELABEL]]: [[LASTNAMEVALUE]]<br>';

        // check if "Doppelmitgliedschaft" has been selected - otherwise do not add these 2 fields to the mail body
        if (str_contains($form->getValue('auswahl'), 'Doppelmitgliedschaft')) {
            $body .= '[[FIRSTNAME2LABEL]]: [[FIRSTNAME2VALUE]]<br>
                [[LASTNAME2LABEL]]: [[LASTNAME2VALUE]]<br>';
        }

        $body .= '[[ADRESSEVALUE]]<br>
            [[PLZVALUE]]&nbsp;
            [[ORTVALUE]]<br>
            [[EMAILVALUE]]<br>
            [[PHONELABEL]]: [[PHONEVALUE]]<br>
            [[GEBLABEL]]: [[GEBVALUE]]<br><br>
            [[KREDITINSTITUTLABEL]]: [[KREDITINSTITUTVALUE]]<br>
            [[KONTOINHABERLABEL]]: [[KONTOINHABERVALUE]]<br>
            [[BICLABEL]]: [[BICVALUE]]<br>
            [[IBANLABEL]]: [[IBANVALUE]]<br><br>';

        // send the form with WireMail
        $m = wireMail();

        if ($form->getValue('sendcopy')) {
            // send copy to sender
            $m->to($form->getValue('email'));
        }

        $m->to('mail@mail.de')// please change this email address to your own
        ->from($form->getValue('email'))
            ->subject('Ein neuer Mitgliedsantrag von ' . $form->getValue('firstname') . ' ' . $form->getValue('lastname'))
            ->title('<h1>Neuer Mitgliedsantrag</h1>') // this is a new property from this module
            ->bodyHTML($body)
            ->sendAttachments($form);

        if (!$m->send()) {
            $form->generateEmailSentErrorAlert(); // generates an error message if something went wrong during the sending process
        }


    }

    $content .= $form->render();

    echo $content;

I have added some additional validation rules to certain fields, some data attributes for the Javascript and some custom labels. Please replace this code with yours (but backup your code first ? ).

To show/hide that name fields for the second person, you will need this little JavaScript snippet.

<script>
    let auswahl = document.getElementsByName("contact-auswahl");
    if(auswahl.length){
    // add event listener to these radio buttons
    auswahl.forEach(function(elem) {
        elem.addEventListener("click", function() {
            let selected = elem.getAttribute('data-value');
            let firstname = document.getElementById('firstname-wrapper');
            let lastname = document.getElementById('lastname-wrapper');
            if(selected == '2'){
                firstname.style.display = 'block';
                lastname.style.display = 'block';
            } else {
                // hide the fields
                firstname.style.display = 'none';
                lastname.style.display = 'none';
                
            }
        });
    });
    }
</script>

Please add it to your template (fe before the closing body tag).

That is all -> the form should work as expected. So please try it out.

What I have not done is to make the name fields of the second name required if "Doppelmitgliedschaft" has been selected. It does not work with the "requiredWith" validator. So for this usecase a new validator has to be developed. Maybe I will try to develop this new validator and add it to the next update.

Best regards

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

@Juergen wow!

So good! Thanks for putting this up. This helps a lot. Not just for this form, I can actually learn from how you've rewritten certain snippets of this code.

Thanks again!

  • Like 3
Link to comment
Share on other sites

Hello @Juergen. First of all I want to thank you for releasing this module for free. I can tell from the code, that A LOT of work went into it.

I want to make some suggestions for improvement, as I stumbled across some errors or hickups that occured in my setup.

I am using FrontendForms 2.2.2 and ProcessWire 3.0.235.

Module settings timeout with many pages
After the first install of the module and trying to go to the modules settings, the page loaded forever and then timed out.
I figured, that the timeout results while trying to get the selectable pages for the data privacy page: https://github.com/juergenweb/FrontendForms/blob/main/FrontendForms.module#L1831-L1840
As I have some tens of thousands of pages it takes too long to process. So I changed the code to use a PageListSelect (treemenu) instead, which I think is much better. 

   // Select the data privacy page
    $dataPrivacySelect = $this->wire('modules')->get('InputfieldPageListSelect');
    $dataPrivacySelect->attr('name', 'input_privacy');
    $dataPrivacySelect->label = $this->_('Privacy policy page');
    $dataPrivacySelect->description = $this->_('Select the page which contains your privacy policy.');
    $dataPrivacySelect->notes = $this->_('The link to this page will be used inside the Privacy class for generating the "Accept the privacy policy" checkbox.');
    $dataPrivacySelect->parent_id = 1; // Set this to the ID of the parent page you want to start the tree from

What you think of that?

Placeholders in email don't work

Then I tried to use the placeholder functionality for the emails, but the placeholders don't get replaced. I attached my form to this post, so you can replicate it.
Is there anything else I need to setup, to get them replaced? Did I miss some instructions? I took the example from https://github.com/juergenweb/FrontendForms/blob/main/Examples/contactformWithWireMailSMTPModule.php and this is the result:

image.png.efad87a35439159fedd5ee6d3aaa4d56.png

File Upload Size does not work correctly

I have a file upload in my form, and want to set a custom max filesize. So I used the rule 

$fileUpload->setRule('allowedFileSize', 2028);

and get the output "Custom Filesize Please do not upload files larger than 2,0 kB" which is correct.

Now I want to set this to 10 megabytes which would be 10 * 1024 * 1024.
As soon as I try to set this as the rule, it is falling back to an incorrect read upload_max_filesize from the php.ini.
The value set in my php.ini is 100M (megabytes)
image.png.f775f113601920fed445323327a19df3.png

So after setting the rule to 

$fileUpload->setRule('allowedFileSize', 10 * 1024 * 1024);

I get the notice under the file upload field "Please do not upload files larger than 100,0 kB" which is wrong. It should either be the 10MB that I set in my rule, or the 100M that is set in the php.ini file.

Thank you in advance for your answer. If you like to discuss personally, we can schedule a call. I would be happy to get to know you.

Another thing: I made my own TailwindCSS adapter which was very easy, with the json files for the other frameworks as a base.

contact.php

  • Like 3
Link to comment
Share on other sites

Hello @dotnetic

First of all, thanks for the detailled report and your suggestions. I am very busy at the moment, so please be patient, I will check all things that you have reported.

Timeout issue:

14 hours ago, dotnetic said:

So I changed the code to use a PageListSelect (treemenu) instead, which I think is much better. 

This could be possible solution. As I can rememeber, Ryan has also implemented queries for very large amounts of pages (like findMany) to prevent timeouts, but I have to dig into it a little bit more.

Placeholder issue:

From the first view it seems that everything is ok, but I will test it on my local installation. A few time ago, I have helped another user by a form using placeholders and it has worked as expected. (Take a look here). So for the moment I have not find a reason why it should not work, but I have to dive in a little bit deeper.

File size issue:

You can always disable the php ini file-size validator by setting

$field->removeRule('phpIniFilesize')

This removes the php.ini file-size validation, but this does not solve the wrong conversion of 10M to 100kb. I guess there is only a simple calculations issue responsible for this mistake. I will check out the function which is responsible for the conversion and I guess I can solve this problem very soon.?

Only to mention: It is going very busy at the moment, so I have not the time to react within a short time and offer a solution promptly, but I will try to solve all these issues until the end of this week and give you an info here.

Best regards and thanks for reporting this issues!!

Jürgen

  • Like 1
Link to comment
Share on other sites

45 minutes ago, Juergen said:

As I can rememeber, Ryan has also implemented queries for very large amounts of pages (like findMany) to prevent timeouts,

Yes, but this would not fix the problem as you would have a select field with tens of thousands of options, which would be unusable.

46 minutes ago, Juergen said:
$field->removeRule('phpIniFilesize')

Thanks, that helps for now.

46 minutes ago, Juergen said:

This removes the php.ini file-size validation, but this does not solve the wrong conversion of 10M to 100kb. I guess there is only a simple calculations issue responsible for this mistake.

The problem is the line https://github.com/juergenweb/FrontendForms/blob/main/Formelements/Inputelements/Inputfields.php#L238 which just converts the setting "10M" to 10 and then multiplicates this by 1024 which would be 100 kilobytes without taking care of the letter M which stands for Megabytes. There might be other settings like G for gigabytes.

The strange thing is, that the PHP documentation mentions that this value is an integer, but shows that the default value is "2M". ?

Link to comment
Share on other sites

1 hour ago, Juergen said:

It is going very busy at the moment

I feel you. Same here.

Is there any possibilty to add custom markup with hidden fields into the form? Thats because I have shopping cart and its items are only stored in the browser local storage. So i want to dynamically inject them into the form, but that would only be possible if I can add custom markup.

Link to comment
Share on other sites

9 minutes ago, dotnetic said:

Is there any possibilty to add custom markup with hidden fields into the form?

Can you give an example of such a markup with a hidden field (HTML that should be outputted)?

Link to comment
Share on other sites

Sure. Here is how I did it before in another Forms module. It uses alpinejs to generate the items

 $form->addMarkup("<p class='mt-5'>Artikel auf deiner Wunschliste:</p>");
    $form->addMarkup('<template x-for="item in $store.cart.cart" :key="item.id" n:syntax="double" x-data>');
    $form->addMarkup('<div class="">');
    $form->addMarkup('<p x-text="`${item.id} (${item.number})`" class=""></p>');
    $form->addMarkup('<input type="hidden" name="wunschliste[]" :value="item.id" class=""></input>');
    $form->addMarkup('</div>');
    $form->addMarkup('</template>');

 

Link to comment
Share on other sites

Ok, I see.

You have the possibility to add  markup before and after an inputfield using these methods: prepend(), append()

This means you have to create the hidden input first and then you prepend (add markup before) and append (add markup afterwards to the input field) your desired markup.

$myhiddenfield = new InputfieldHidden('wunschliste[]');
$myhiddenfield->setAttribute(':value', 'item.id');
$myhiddenfield->prepend("<div>")->append('</div>');  

You have to replace the "div" with the markup you want to display before and afterwards. That is the only possibiltity at the moment, that could work in your case.

Link to comment
Share on other sites

Hello @dotnetic

it seems that the placeholder does not work, if you add placeholders where no appropriate formfield exists.

In your case, you have set

[[FIRSTNAME2LABEL]]: [[FIRSTNAME2VALUE]]<br>
[[LASTNAME2LABEL]]: [[LASTNAME2VALUE]]<br>

but there are no form fields with this name attribute set and this will probably stop the replacement of the placeholder with actual values.

So please remove all placeholders, where no appropriate form field exist and tell me if it works. If yes I will update the function that is responsible for replacing the placeholders with values, so it will ignore those placeholders in the future.

Ok that was not the reason, I have created the form code with placeholders that works.  The only thing I have found was that you have set

$body = $m->title;

before you have initialized $m - that will not work. So please try this form.

Best regards Jürgen

contact-rewritten.php

Link to comment
Share on other sites

Hello @dotnetic

I have found the solution for your placeholder problem. It is so simple, but I have overread it multiple times ?!

For all other users:

You have to name the placeholders for the label and the value as a combination of the field name + label or value. Here is an example:

Your have the following field inside your form:

$name = new \FrontendForms\InputText('Vorname');
        $name->setLabel('Vorname');
        $name->setRule('required')->setCustomMessage('Dieses Feld muss ausgefüllt werden.');
        $form->add($name);

The name of the field is "Vorname", which is the German word for "First name".

The placeholder for the label of the field is [[VORNAMELABEL]] = name of the field + label

The placeholder for the value of the field is [VORNAMEVALUE]] = name of the field + value

As you can see the placeholders are always a combination of the name and the word "label" or "value".

 

@dotnetic the mistake in your case was that you have taken the placeholder values from another example as you have written:

image.png.5ecb803cd14d697def9271c5b81478fd.png

As you can see the placeholders do not match with the names of your formfield. GENDERLABEL must be ANREDELABEL in your case because your gender field has the name attribute "Anrede" and so on.

So please take care that your placeholder names match your field names. Otherwise the placeholders will not be replaced inside your mail template.?

Link to comment
Share on other sites

10 hours ago, dotnetic said:
 $form->addMarkup("<p class='mt-5'>Artikel auf deiner Wunschliste:</p>");
    $form->addMarkup('<template x-for="item in $store.cart.cart" :key="item.id" n:syntax="double" x-data>');
    $form->addMarkup('<div class="">');
    $form->addMarkup('<p x-text="`${item.id} (${item.number})`" class=""></p>');
    $form->addMarkup('<input type="hidden" name="wunschliste[]" :value="item.id" class=""></input>');
    $form->addMarkup('</div>');
    $form->addMarkup('</template>');

This is the code that should work to get the desired markup:

$myhiddenfield = new \FrontendForms\InputHidden('wunschliste[]');
$myhiddenfield->setAttribute(':value', 'item.id');
$prepend = '<p class="mt-5">Artikel auf deiner Wunschliste:</p>
<template x-for="item in $store.cart.cart" :key="item.id" n:syntax="double" x-data>
  <div class="">';
    $append = '</div></template>';
$myhiddenfield->prepend($prepend)->append($append);
$form->add($myhiddenfield);

If "$store.cart.cart" should be a PHP variable you have to adapt the code a little bit with "'".

  • Like 2
Link to comment
Share on other sites

Hi @Juergen! I come with a small question, in my form, I'd like to have a text input for a unique code that users receive personally beforehand; the idea is that I will store a csv file somewhere and for the form to be valid, the input needs to match one of the codes within the csv. Any suggestion on how to do this based on the module? I imagine that it is pretty similar to the CAPTCHA question system but maybe there is a better way? Thank you so much for the module, it is truly amazing to work with !

  • Like 1
Link to comment
Share on other sites

Hello @marie.mdna

glad to hear that you like it.?

My idea for your scenario: You will need to load the codes from the file into an array (for example with the file_get_contents method from PHP).

If you have your codes inside an array

$codes = ['123456', 2849567','7899965']

you can use the built in_array check validator, which is called "listContains":

$field->setRule('listContains', $codes)->setCustomMessage('Unfortunately the code you have entered is not correct.');

This validator returns true if the code that the user has entered is found inside the array and false if not.

This validator is part of the Valitron library, therefore I have not described it inside my docs, but you can read more about it inside the docs of the valitron library.

Tipp: Take a look at all validators, inside the docs of the Valitron library - there are a lot and they will not be explained in my docs, because they are part of Valitron, but you can use it in the same way as my custom validators.

Best regards Jürgen

  • Like 1
Link to comment
Share on other sites

Maybe the "in" validator could also be solution in your case, but to be honest, I do not know what the difference is between the "in" and the "listContains" validator.?

It seems the "listContains" is for entering a list as value and the "in" for entering a single value to be compared with a list. So the "in" would probably the better choice in your case, but you need to try it out.

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...