<p>Not sure I have the full picture yet, but as per the comments, the problem appears to be clear:</p>
<blockquote>
<p>I think I found the issue. Before, I was disabling the form first and then submitting it. That was working well, but not anymore. However, if I change the order in the JS execution, submitting first, and then disabling, things work as they used to.</p>
</blockquote>
<p>If you're disabling the form's input elements using the <code>disabled</code> attribute before sending it, an empty post body is expected. Disabled input elements aren't included in the submitted form, this is <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled" rel="nofollow noreferrer">by design</a>. Not sure why it ever worked before, but in this case, submitting the form first and then disabling the inputs will solve the issue. Or just disable the submit button to prevent duplicate submissions and leave the rest of the inputs alone.</p>
<p>Another possibility would be to submit the <code>FormData</code> object with a <code>fetch()</code> call – of course, this is only practical if you want to handle the response in JavaScript.</p>
<hr />
<p>For future readers:</p>
<blockquote>
<p>I don't remember seeing the long string of characters in the redirect
input's value. Instead I thought it would be something like this
<code>thank-you?from{fromName}</code> only.</p>
</blockquote>
<p>This is working as intended, the long string of characters is a hashed value. Craft <a href="https://github.com/craftcms/cms/blob/develop/src/helpers/Html.php#L88-L104" rel="nofollow noreferrer">hashes the redirect URL</a> to prevent tampering. See <a href="https://www.yiiframework.com/doc/api/2.0/yii-base-security#hashData()-detail" rel="nofollow noreferrer">Security::hashData</a> for details.</p>

CC BY-SA 4.0
2021-11-05T22:08:58.873Z
thank you for the clarifications. The problem was indeed the attempt to submit the form after disabling the fields. Strange that Firefox was letting that pass through. Really, really appreciate the help. Wish I could change the title of this post.
mauricio
CC BY-SA 4.0
2021-11-08T10:17:25.370Z
@mauricio Glad I could help! You can change the title of the question, there should be a small `Edit` link at the bottom of your question. Not sure if that requires a particular privilege though, as far as I know it shouldn't for your own question.
MoritzLost
CC BY-SA 4.0
2021-11-09T14:31:59.883Z
awesome, this was a lack of attention! I didn't realize that one can also edit the question title. Thank you so much!
mauricio
CC BY-SA 4.0
2021-11-05T15:08:18.373Z
2021-11-05T15:08:18.373Z
MoritzLost
<p>I have a site with Pixel &amp; Tonic's contact form. This site is built using Nitro. The contact form has a 'post' submit, and a page redirect to a thank you page if the form is sent properly. There's not Ajax involved.</p>
<p>The form was working well. I'm not sure if this is just a mere coincidence, but I upgraded today to the latest CraftCMS version (3.17.19) and, my default browser, Firefox, was updated too. Afterwards I noticed the problem. The form's version is 2.2.7.</p>
<p>I have inline JS validation before sending. This part is working. And when the inputs are valid, there's an attempt to submit the form.</p>
<p>Examining the network traffic, I see that the Request parameters in the post call, are empty (Firefox reports it as <code>No payload for this request</code>). I was expecting to see the submitted data.</p>
<p>Also I noticed something a bit puzzling. The form has this code:</p>
<pre class="lang-PHP prettyprint-override"><code>{{ csrfInput() }}
{{ redirectInput('thank-you?from={fromName}') }}
</code></pre>
<p>Which in the frontend, are rendered like this:</p>
<pre class="lang-HTML prettyprint-override"><code>&lt;input type=&quot;hidden&quot; name=&quot;CRAFT_CSRF_TOKEN&quot; value=&quot;UWOm80Y6Hu-ADjHBk2qH8Ds8C3MHSxut0scjX4O6skpfvZkNDtu7ySpoebWma8RJF5JLXUlCotOkyETtdhWK1BAGGjth2yploNIRzC-paXQyZslvGa5l65dG8dcBv_MNb_uBvUvwe2LzzdZHvnEtwZnHujgJHdkJ2uBEC8fX4JMWpgGYfBzsFnjoNZ4aFddqnz4i2SNtA2-A2ErBfvV-RjZTQx4YjYFZxsgKZDupMACKXTvnjCWXMRirSegj7lOXjqCT-aQYli9tB7tk9iIfBQhQ98QEYDOH9Fh7kN4kxL9Ua1MYbiVD9L6SWzjtjdACDdP9YX6O7J1WWxqHk138eSOlfW4tcMO1kP8l3UItueN1YCMMUelPUZCwJPlKkV4XBlL9VimZVt-gJ5S2Nd7FO1zN4tgokh5bkpTlFokzd-zxs-xyWFCXSpWPE1Osvo7LT8pU4Bty23Qwulv6dmWCPctCE6UHX3pLsetumVCiGzZZAgdrVtvGMoj4QSVimkF5pDRIlrln-HxL2SCgYKVl_faV9a6dIeIeGTbTF7d7Uko=&quot;&gt;
&lt;input type=&quot;hidden&quot; name=&quot;redirect&quot; value=&quot;86f9c378e703b2be657e4a742b9ff62ab3909e6c2ebb2cc64ad7a6ed7495dfc3thank-you?from={fromName}&quot;&gt;
</code></pre>
<p>I don't remember seeing the long string of characters in the redirect input's value. Instead, I thought it would be something like this <code>thank-you?from{fromName}</code> only.</p>
<p>I wonder if the update is the reason behind this problem. Thanks so much for your help.</p>
<p><strong>EDIT</strong>
When I disable the JS validation, the contact form works well. However, when it is enabled, the sent post request is empty. I'm pasting below the validation script. What I find strange is that right before doing a <code>form.submit()</code>, I'm logging the FormData parameters, and all the entered information is logged(!).</p>
<pre class="lang-js prettyprint-override"><code>&lt;script&gt;
    (function() {
        // form elements
        const form = document.querySelector(&quot;.contactForm&quot;);
        const form_button = form.querySelector(&quot;.outsetSend&quot;);
        const fieldset = form.querySelector('fieldset');
        
        // Adds listener to the form
        formListener = ()=&gt;{
            form.addEventListener(&quot;submit&quot;, e =&gt; {
                e.preventDefault();
                let formData = new FormData(form);
                // Validates form, returns false when there's no errors
                if ( !formErrors(formData) ) {
                    // logs the data the form validated 
                    for(var pair of formData.entries()) {
                       console.log(pair[0]+ ': '+ pair[1]);
                    }
                    // shows spinner and disables fields and buttons
                    hyper.formSending();
                    // sends form 
                    form.submit();
                }
                return false;
            });
        };
        
        // adds listener to required fields so that error messages hide when field is on focus
        requiredFieldsListener = ()=&gt;{
            // figures which fields are required
            let required = form.querySelectorAll(&quot;[required]&quot;);
            // Adds listener to each entry
            for (let i = 0; i &lt; required.length; ++i) {
               required[i].addEventListener('focus', e =&gt;{
                   let parent = e.target.closest(&quot;.outsetField&quot;);
                   parent.classList.remove('validationError');
                   // removes text content
                   let errorArea = parent.querySelector('.outsetField-error');
                   errorArea.textContent = '';
               } );
            }
        };

        // Validates form
        // Checks for errors in the contact form submission
        // returns false when there's no errors
        formErrors = (formData)=&gt;{
            let error = false;
            let errorArray = new Array();
            let toValidate = new Array();

            // checks if there's a honeypot field AND if it is filled
            if (formData.get('myInterest') !== null &amp;&amp; formData.get('myInterest')  != ''){
                // honeyF violation, we should abort here
                // console.log ('HoneyPot Error')
                finalMessage();
                return true;
            }
            
            // figures which fields are required
            let required = form.querySelectorAll(&quot;[required]&quot;);
            // creates an array with required fields, Each entry is an object
            for (let i = 0; i &lt; required.length; ++i) {
                toValidate.push({
                    id: required[i].getAttribute(&quot;id&quot;),
                    type: required[i].getAttribute(&quot;type&quot;),
                    value: required[i].value,
                    placeholder: required[i].getAttribute(&quot;placeholder&quot;),
                    name: required[i].name,
                });
            }

            // Figures which required fields are invalid
            for (const element of toValidate) {
                if (element.type == &quot;text&quot; &amp;&amp; element.value.length == 0) {
                    // Checks none of the text fields, including email, is empty
                    error = true;
                    // adds new error message to object 
                    element.errorMessage = &quot;Please enter &quot; + element.placeholder;
                    errorArray.push(element);
                }  else if (element.type == &quot;text&quot; &amp;&amp; element.name == 'fromEmail' &amp;&amp; element.value.length &gt; 0) {
                    // specific to the email field validation
                    const re =
                    /^(([^&lt;&gt;()[\]\\.,;:\s@\&quot;]+(\.[^&lt;&gt;()[\]\\.,;:\s@\&quot;]+)*)|(\&quot;.+\&quot;))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
                    let emailValid = re.test(element.value);
                    if (!emailValid) {
                        error = true;
                        element.errorMessage = &quot;Please review &quot; + element.placeholder;
                        errorArray.push(element);
                    }
                }
            }
            if (error == true) {
                // displays errors
                insertErrors(errorArray);
            }
            console.log('VALIDATION FAILED?=',error);
            return error;
        };

        // Receives error array and displays error messages associated with validation of input
        insertErrors = (errorArray) =&gt; {
            for (const element of errorArray) {
                const el = document.querySelector(&quot;#&quot; + element.id);
                const parentEl = el.parentElement;
                const errorEl = parentEl.querySelector(&quot;.outsetField-error&quot;);
                parentEl.classList.add(&quot;validationError&quot;);
                errorEl.innerHTML = element.errorMessage;
            }
        };        

        /* {# Shows failure message when the error is not due to direct user input #}
         {# for instance, the hidden honeypot field has been filled. Or there's missing key inputs #} */
        finalMessage = () =&gt; {
            hyper.failureMessage();
        };

        // Initiates the form and listeners for the required fields
        formListener();
        requiredFieldsListener();
        
  })();  
&lt;/script&gt;
</code></pre>

CC BY-SA 4.0
2021-11-05T09:00:18.203Z
The long string of characters is normal, Craft [hashes the redirect URL](https://github.com/craftcms/cms/blob/develop/src/helpers/Html.php#L88-L104) to prevent tampering. Since Firefox shows an empty request body, it's likely an error with either the form HTML or the JS validation, can you post the full code for those?
MoritzLost
CC BY-SA 4.0
2021-11-05T12:36:19.040Z
Thank you so much for your answer. I spent many hours yesterday trying to figure out what was wrong with the form. It's nice to hear that the long strings are expected.
When you asked to see the JS validation, i decided to turn it off and test submitting the form without it. To my surprise it worked! So I'm not sure how, and when, the validation, that was working starting acting out. Before posting more I'm going to review it and try to figure it out what is going on. The validation code is quite long. If I get stuck I'll be posting it here. Thank you so much.
mauricio
CC BY-SA 4.0
2021-11-05T13:36:05.247Z
You're welcome! If you post the validation code I'll see if I spot any errors, sometimes it's easier with a fresh pair of eyes :)
MoritzLost
CC BY-SA 4.0
2021-11-05T14:16:51.263Z
@MoritzLost Thanks so much for taking the time to look at this. I have reviewed the JS routine several times and cannot find what's going on. So I pasted the script in the original post above. Thank you so much for looking at it.
mauricio
CC BY-SA 4.0
2021-11-05T14:27:18.343Z
@MoritzLost I think I found the issue. Before, I was disabling the form first and then submitting it. That was working well, but not anymore. However, if I change the order in the JS execution, submitting first, and then disabling, things work as they used to. Besides updating CraftCMS, the other only change in my setup was an update to Firefox Developer Edition. Perhaps this latest Firefox version handles things differently when a form is disabled?
mauricio
CC BY-SA 4.0
2021-11-05T14:55:22.823Z
Just looking through it … what's the `hyper` variable? Some external library? What does `hyper.formSending();` do?
MoritzLost
CC BY-SA 4.0
2021-11-05T22:07:31.410Z
@MoritzLost, thank you so much for taking the time to look through things. I've learned quite a bit. Not sure why Firefox was letting me send the form after the fields had been disabled. But thank you for clarifying. And also thank you for the explanation on the hashing.
Regarding the hyper variable, I'm using hyperscript (https://github.com/hyperhype/hyperscript) for the UX interactions. I'm liking it quite a bit, but it takes a little bit getting used to the syntax.
mauricio
<plugin-contactform>
Contact form not working since Firefox version update
# Contact form not working since Firefox version update

(Asked by: username_0 on 2021-11-05)

I have a site with Pixel & Tonic's contact form. This site is built using Nitro. The contact form has a 'post' submit, and a page redirect to a thank you page if the form is sent properly. There's not Ajax involved.
The form was working well. I'm not sure if this is just a mere coincidence, but I upgraded today to the latest CraftCMS version (3.17.19) and, my default browser, Firefox, was updated too. Afterwards I noticed the problem. The form's version is 2.2.7.
I have inline JS validation before sending. This part is working. And when the inputs are valid, there's an attempt to submit the form.
Examining the network traffic, I see that the Request parameters in the post call, are empty (Firefox reports it as No payload for this request). I was expecting to see the submitted data.
Also I noticed something a bit puzzling. The form has this code:
{{ csrfInput() }}
{{ redirectInput('thank-you?from={fromName}') }}

Which in the frontend, are rendered like this:



I don't remember seeing the long string of characters in the redirect input's value. Instead, I thought it would be something like this thank-you?from{fromName} only.
I wonder if the update is the reason behind this problem. Thanks so much for your help.
EDIT
When I disable the JS validation, the contact form works well. However, when it is enabled, the sent post request is empty. I'm pasting below the validation script. What I find strange is that right before doing a form.submit(), I'm logging the FormData parameters, and all the entered information is logged(!).

**Tags:** plugin-contactform

> **Comments:**
> **username_1**: The long string of characters is normal, Craft [hashes the redirect URL](https://github.com/craftcms/cms/blob/develop/src/helpers/Html.php#L88-L104) to prevent tampering. Since Firefox shows an empty request body, it's likely an error with either the form HTML or the JS validation, can you post the full code for those?  
> **username_0**: Thank you so much for your answer. I spent many hours yesterday trying to figure out what was wrong with the form. It's nice to hear that the long strings are expected. When you asked to see the JS validation, i decided to turn it off and test submitting the form without it. To my surprise it worked! So I'm not sure how, and when, the validation, that was working starting acting out. Before posting more I'm going to review it and try to figure it out what is going on. The validation code is quite long. If I get stuck I'll be posting it here. Thank you so much.  
> **username_1**: You're welcome! If you post the validation code I'll see if I spot any errors, sometimes it's easier with a fresh pair of eyes :)  
> **username_0**: @username_1 Thanks so much for taking the time to look at this. I have reviewed the JS routine several times and cannot find what's going on. So I pasted the script in the original post above. Thank you so much for looking at it.  
> **username_0**: @username_1 I think I found the issue. Before, I was disabling the form first and then submitting it. That was working well, but not anymore. However, if I change the order in the JS execution, submitting first, and then disabling, things work as they used to. Besides updating CraftCMS, the other only change in my setup was an update to Firefox Developer Edition. Perhaps this latest Firefox version handles things differently when a form is disabled?  
> **username_1**: Just looking through it … what's the `hyper` variable? Some external library? What does `hyper.formSending();` do?  
> **username_0**: @username_1, thank you so much for taking the time to look through things. I've learned quite a bit. Not sure why Firefox was letting me send the form after the fields had been disabled. But thank you for clarifying. And also thank you for the explanation on the hashing. Regarding the hyper variable, I'm using hyperscript (https://github.com/hyperhype/hyperscript) for the UX interactions. I'm liking it quite a bit, but it takes a little bit getting used to the syntax.  

---

## 1 answers

### Answer by username_1 on 2021-11-05. Score: 2 | Accepted answer

Not sure I have the full picture yet, but as per the comments, the problem appears to be clear:

> I think I found the issue. Before, I was disabling the form first and then submitting it. That was working well, but not anymore. However, if I change the order in the JS execution, submitting first, and then disabling, things work as they used to.

If you're disabling the form's input elements using the `disabled` attribute before sending it, an empty post body is expected. Disabled input elements aren't included in the submitted form, this is [by design](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled). Not sure why it ever worked before, but in this case, submitting the form first and then disabling the inputs will solve the issue. Or just disable the submit button to prevent duplicate submissions and leave the rest of the inputs alone.

Another possibility would be to submit the `FormData` object with a `fetch()` call – of course, this is only practical if you want to handle the response in JavaScript.

---

For future readers:

> I don't remember seeing the long string of characters in the redirect
> input's value. Instead I thought it would be something like this
> `thank-you?from{fromName}` only.

This is working as intended, the long string of characters is a hashed value. Craft [hashes the redirect URL](https://github.com/craftcms/cms/blob/develop/src/helpers/Html.php#L88-L104) to prevent tampering. See [Security::hashData](https://www.yiiframework.com/doc/api/2.0/yii-base-security#hashData()-detail) for details.

> **Comments:**
> **username_0**: thank you for the clarifications. The problem was indeed the attempt to submit the form after disabling the fields. Strange that Firefox was letting that pass through. Really, really appreciate the help. Wish I could change the title of this post.  
> **username_1**: @username_0 Glad I could help! You can change the title of the question, there should be a small `Edit` link at the bottom of your question. Not sure if that requires a particular privilege though, as far as I know it shouldn't for your own question.  
> **username_0**: awesome, this was a lack of attention! I didn't realize that one can also edit the question title. Thank you so much!  

---

