How to change URL form with GET method? - forms

Form:
<form action="/test" method="GET">
<input name="cat3" value="1" type="checkbox">
<input name="cat3" value="5" type="checkbox">
<input name="cat3" value="8" type="checkbox">
<input name="cat3" value="18" type="checkbox">
<input type="submit" value="SUBMIT">
</form>
How to change URL form with GET method?
Before: test?cat3=1&cat3=5&cat3=8&cat3=18
After: test?cat3=1,5,8,18
I want to use jQuery.
Many thanks!

Here you go! This example, using jQuery, will grab your form elements as your question is asking and perform a GET request to the desired URL. You may notice the commas encoded as "%2C" - but those will be automatically decoded for you when you read the data on the server side.
$(document).ready(function(){
$('#myForm').submit(function() {
// Create our form object. You could optionally serialize our whole form here if there are additional parameters in the form you want
var params = {
"cat3":""
};
// Loop through the checked items named cat3 and add to our param string
$(this).children('input[name=cat3]:checked').each(function(i,obj){
if( i > 0 ) params.cat3 += ',';
params.cat3 += $(obj).val();
});
// "submit" our form by going to the properly formed GET url
var url = $(this).attr('action') + '?' + $.param( params );
// Sample alert you can remove
alert( "This form will now GET the URL: " + url );
// Perform the submission
window.location.href = url;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="/test" method="GET" id="myForm">
<input name="cat3" value="1" type="checkbox">
<input name="cat3" value="5" type="checkbox">
<input name="cat3" value="8" type="checkbox">
<input name="cat3" value="18" type="checkbox">
<input type="submit" value="SUBMIT">
</form>

My friend found a solution:
$(document).ready(function() {
// Change Url Form: &cat3=0&cat3=1&cat3=2 -> &cat3=0,1,2
var changeUrlForm = function(catName){
$('form').on('submit', function(){
var myForm = $(this);
var checkbox = myForm.find("input[type=checkbox][name="+ catName +"]");
var catValue = '';
checkbox.each(function(index, element) {
var name = element.name;
var value = element.value;
if (element.checked) {
if (catValue === '') {
catValue += value;
} else {
catValue += '‚' + value;
}
element.disabled = true;
}
});
if (catValue !== '') {
myForm.append('<input type="hidden" name="' + catName + '" value="' + catValue + '" />');
}
});
};
// Press 'Enter' key
$('.search-form .inputbox-search').keypress(function(e) {
if (e.which == 13) {
changeUrlForm('cat3');
changeUrlForm('cat4');
alert(window.location.href);
}
});
// Click to submit button
$('.search-form .btn-submit').on('click', function() {
changeUrlForm('cat3');
changeUrlForm('cat4');
alert(window.location.href);
$(".search-form").submit();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="/test" method="GET" class="search-form">
<input name="cat3" value="1" type="checkbox">1
<input name="cat3" value="3" type="checkbox">3
<input name="cat3" value="5" type="checkbox">5
<input name="cat3" value="7" type="checkbox">7
<br />
<input name="cat4" value="2" type="checkbox">2
<input name="cat4" value="4" type="checkbox">4
<input name="cat4" value="6" type="checkbox">6
<br />
<br />
Submit
<br />
<br />
<input type="text" placeholder="Search" class="inputbox-search" />
</form>

Related

Why am I getting "500 (Internal Server Error)" and "Uncaught (in promise) SyntaxError: Unexpected token < "?

I am trying to insert some data into the database through a fetch API POST request to a Next.js API route but I am getting the following two error messages in the browser's console:
api/addCompany/addCompany:1 Failed to load resource: the server responded with a status of 500 (Internal Server Error) register:1
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
These are my project's folders (it's relevant because of Next.js's routing system)
This is the component where I am doing the fetch API request (please don't judge my poor Typescript skills, I am new to it, still not finding the propper event type):
import styles from '../styles/Register.module.css'
import { NextPage } from "next"
import { prisma } from '../prisma/prisma_client';
import { Prisma } from '#prisma/client';
import { useSession } from "next-auth/react"
const Register: NextPage = () => {
const createCompany: any = async (event: any) => {
event.preventDefault()
const company: Prisma.CompanyCreateInput = {
companyName: event.target.companyName.value,
gender: event.target.gender.value,
firstName: event.target.firstName.value,
lastName: event.target.lastName.value,
street: event.target.street.value,
houseNumber: parseInt(event.target.houseNumber.value),
postcode: parseInt(event.target.postcode.value),
city: event.target.city.value,
country: event.target.country.value,
countryCode: event.target.countryCode.value,
callNumber: parseInt(event.target.callNumber.value),
emailAddress: event.target.emailAddress.value,
website: event.target.website.value,
socials: {},
companyUser: {
connect: { id: 'cl0y4y8xo0021mwtcmwlqfif6' }
}
}
const companyJSON = JSON.stringify(company)
const endpoint = '/api/addCompany/addCompany'
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: companyJSON,
}
const response = await fetch(endpoint, options)
const data = await response.json()
console.log(data)
}
return (
<form onSubmit={createCompany} className={styles.form} id="signupForm" noValidate>
<h2>Company Information</h2>
<div className="fieldWrapper">
<input type="text" id="companyName" name="companyName" placeholder=" " />
<label htmlFor="companyName">Company Name<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" list="genders" id="gender" name="gender" placeholder=" " />
<label htmlFor="gender">Gender<span>*</span></label>
<div className='errorMessage'></div>
<datalist id="genders">
<option>Female</option>
<option>Male</option>
</datalist>
</div>
<div className="fieldWrapper">
<input type="text" id="firstName" name="firstName" placeholder=" " />
<label htmlFor="firstName">First Name<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" id="lastName" name="lastName" placeholder=" " />
<label htmlFor="lastName">Last Name<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" id="street" name="street" placeholder=" " />
<label htmlFor="street">Street<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="number" id="houseNumber" name="houseNumber" placeholder=" " />
<label htmlFor="houseNumber">House Number<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="number" id="postcode" name="postcode" placeholder=" " />
<label htmlFor="postcode">Postcode<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" id="city" name="city" placeholder=" " />
<label htmlFor="city">City<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" id="country" name="country" placeholder=" " />
<label htmlFor="country">Country<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" id="countryCode" name="countryCode" placeholder=" " />
<label htmlFor="countryCode">Country Code<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="number" id="callNumber" name="callNumber" placeholder=" " />
<label htmlFor="callNumber">Call Number<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="email" id="emailAddress" name="emailAddress" placeholder=" " />
<label htmlFor="emailAddress">Email Address<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className="fieldWrapper">
<input type="text" id="website" name="website" placeholder=" " />
<label htmlFor="website">Website</label>
</div>
<div className="fieldWrapper">
<input type="text" id="socials" name="socials" placeholder=" " />
<label htmlFor="socials">Socials</label>
</div>
<div className="fieldWrapper">
<button type="submit">Save</button>
</div>
</form>
)
}
export default Register
And this is the the addCompany file's code which serves as the Next.js API route for my fetch API request:
import { Prisma } from '#prisma/client';
import { NextApiRequest, NextApiResponse } from 'next';
import { prisma } from '../../../prisma/prisma_client';
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const {body} = req;
const companyData: Prisma.CompanyCreateInput = JSON.parse(body);
const addCompany = await prisma.company.create({
data: companyData
})
res.status(200).json(addCompany);
}
export default handler
I appreciate any help. Thank you.
I tried to comment out
const data = await response.json() console.log(data)
in the Register component so the error "Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0" disappeared but that is no solution to the problem at all.
I also tried to adjust the route of my fetch request to any possible option because I wasn't sure how exactly Next.js autocompletes it, for example I tried: '/api/addCompany/addCompany.ts' and so on.
I expect the problem to be something small, I hope it isn't typo.
Thank you again.
PS: I also checked similar posts on this matter but couldn't find a fix for my problem.
There is no need to reparse the body data in the API endpoint because Next.js middleware convert that data to an object already:
API routes provide built in middlewares which parse the incoming
request (req). Those middlewares are:
req.cookies - An object containing the cookies sent by the request. Defaults to {}
req.query - An object containing the query string. Defaults to {}
req.body - An object containing the body parsed by content-type, or null if no body was sent
something like below should work:
import { Prisma } from '#prisma/client';
import { NextApiRequest, NextApiResponse } from 'next';
import { prisma } from '../../../prisma/prisma_client';
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const {body: companyData} = req;
//const companyData: Prisma.CompanyCreateInput = JSON.parse(body);<- No need to reparse the data here
const addCompany = await prisma.company.create({
data: companyData
})
res.status(200).json(addCompany);
}
export default handler
Thanks to this answer here for clarification.

Salesforce Web-to-Lead form collecting UTM data after browsing multiple pages

I have a salesforce web-to-lead form that is set up to collect utm data, and it does.... if I dont leave the page.
Currently, I am not using sf web to lead form. If the user comes to site from an ad, the utm parameters are stored in a cookie and used if the user completes a form. It works perfectly.
I now am required to use sf web to lead forms. If I land directly on the page and never leave, the utm parameters in url are successfully collected in the form. If I leave page and return to form page, I can see the utm parameters stored in the cookie, but the form does not collect.
Please send help!!!!! I need to be able to navigate away from page and use stored cookie to populate the utm hidden form fields.
<form id="salesforceForm" method="POST" action="https://webto.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8">
<input name="oid" type="hidden" value="mySFID#">
<input name="retURL" type="hidden" value="myredirectlink.com">
<label for="first_name">First Name*</label> <input id="first_name" maxlength="40" name="first_name" required="" size="20" type="text">
<label for="last_name">Last Name*</label> <input id="last_name" maxlength="80" name="last_name" required="" size="20" type="text">
<label for="email">Email*</label> <input id="email" maxlength="80" name="email" required="" size="20" type="text">
<label for="company">Company*</label> <input id="company" maxlength="40" name="company" required="" size="20" type="text"> <label for="phone">Phone*</label> <input id="phone" maxlength="40" name="phone" required="" size="20" type="text">
<input id="utm_source" name="00N50000003KWmr" type="hidden" value="">
<input id="utm_medium" name="00N50000003KWn6" type="hidden" value="">
<input id="utm_campaign" name="00N50000003KWnB" type="hidden" value="">
<input id="utm_term" name="00N50000003KWnG" type="hidden" value="">
<input id="utm_content" name="00N50000003KWnL" type="hidden" value="">
<input name="btnSubmit" type="submit">
</form>
<script type="text/javascript">
function parseGET(param) {
var searchStr = document.location.search;
try {
var match = searchStr.match('[?&]' + param + '=([^&]+)');
if (match) {
var result = match[1];
result = result.replace(/\+/g, '%20');
result = decodeURIComponent(result);
return result;
} else {
return '';
}
} catch (e) {
return '';
}
}
document.getElementById('utm_source').value = parseGET('utm_source');
document.getElementById('utm_medium').value = parseGET('utm_medium');
document.getElementById('utm_campaign').value = parseGET('utm_campaign');
document.getElementById('utm_term').value = parseGET('utm_term');
document.getElementById('utm_content').value = parseGET('utm_content');
</script>
There's nothing here that actually sets the cookie, right? Or reads from it.
I've never actively used Google Tag Manager and you're saying something sets the cookie already...
My gut feel you need something like if(parseGET('utm_source') == ""), then use functions from https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie
This helps?
let utm_source = parseGET('utm_source');
if(!utm_source){
utm_source = document.cookie
.split('; ')
.find(row => row.startsWith('utm_source='))
.split('=')[1];
}
document.getElementById('utm_source').value = utm_source;
?
Untested, you'll have to experiment and put right names of cookies.

radio buttons check and uncheck remove and replace input values

I have two radio buttons with label name A & B and two groups of text boxes with class names groupA and groupB.My requirement is When user checks radiobutton A then all the values from Group B text boxes will clear and when user checks Radiobutton B then GroupB text boxes again fill with their original values and Group A textboxes values will clear vice versa. For this i am able to clear textboxes values based on class.But i how to fill all the previous values when user checks one of the radiobutton?Below is my code.
jQuery(function(){
jQuery("#id1").click(function() {
jQuery(".groupB").each(function()
{
jQuery('input.groupB[type="text"]').val('');
});
}
});
jQuery("#id2").click(function() {
jQuery(".groupA").each(function()
{
jQuery('input.groupA[type="text"]').val('');
});
}
});
});
Any help would be greatly appreciated.
You didn't show your HTML, so I'm not sure I have the fields right. But here is what I came up with:
<body>
<form>
<input id="id1" type="radio" name="test" value="A" />Group A
<input type="hidden" name="hidden_a1" />
<input type="hidden" name="hidden_a2" />
<input class="groupA" type="text" name="text_a1" disabled="disabled" />
<input class="groupA" type="text" name="text_a2" disabled="disabled" />
<br />
<input id="id2" type="radio" name="test" value="B" />Group B
<input type="hidden" name="hidden_b1" />
<input type="hidden" name="hidden_b2" />
<input class="groupB" type="text" name="text_b1" disabled="disabled" />
<input class="groupB" type="text" name="text_b2" disabled="disabled" />
</form>
</body>
and here is the JavaScript code:
$(document).ready(function() {
$('#id1').on('click', {
show: 'A',
hide: 'B'
}, choose_group);
$('#id2').on('click', {
show: 'B',
hide: 'A'
}, choose_group);
});
function choose_group(event) {
$('.group' + event.data.show).each(function(index) {
$(this).prop('value', $('[name="' + $(this).prop('name').replace('text', 'hidden') + '"]').prop('value'));
$(this).prop('disabled', false);
});
$('.group' + event.data.hide).each(function(index) {
$('[name="' + $(this).prop('name').replace('text', 'hidden') + '"]').prop('value',
$(this).prop('value'));
$(this).prop('value', '');
$(this).prop('disabled', true);
});
}

Google geocoder issue on form submit

I have a problem with Google Geocoder API.
I have a form where the user type a full address. When the form is submited, I want to extract the city from this address and put this city in a hidden field.
So here is what I've done...
HTML :
<form id="new_post" name="new_post" method="post" action="" onSubmit="codeAddress()">
<p>
<label for="adresse_de_depart">Adresse de départ</label><br />
<input type="text" id="adresse_de_depart" value="" tabindex="1" size="20" name="adresse_de_depart"/>
</p>
<input type="hidden" id="ville_depart" name="ville_depart" value=""/>
<p align="right">
<input type="submit" value="Publish" tabindex="6" id="submit" name="submit" />
</p>
</form>
JS :
<script>
var geocoder;
$(document).ready(function(){
geocoder = new google.maps.Geocoder();
});
function codeAddress() {
var adresse = document.getElementById("adresse_de_depart").value;
console.log(geocoder);
alert(adresse_de_depart);
geocoder.geocode( { 'address': adresse}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
alert("OK");
document.getElementById("ville_depart").value=results;
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}</script>
The first "alert" works but after the page is reloaded (and the form is submited). But I have no alert related to the geocode method...
Have you got an idea ?
Thanks !

Required attribute on multiple checkboxes with the same name? [duplicate]

This question already has answers here:
Using the HTML5 "required" attribute for a group of checkboxes?
(16 answers)
Closed 6 years ago.
I have a list of checkboxes with the same name attribute, and I need to validate that at least one of them has been selected.
But when I use the html5 attribute "required" on all of them, the browser (chrome & ff) doesn't allow me to submit the form unless all of them are checked.
sample code:
<label for="a-0">a-0</label>
<input type="checkbox" name="q-8" id="a-0" required />
<label for="a-1">a-1</label>
<input type="checkbox" name="q-8" id="a-1" required />
<label for="a-2">a-2</label>
<input type="checkbox" name="q-8" id="a-2" required />
When using the same with radio inputs, the form works as expected (if one of the options is selected the form validates)
According to Joe Hopfgartner (who claims to quote the html5 specs), the supposed behaviour is:
For checkboxes, the required attribute shall only be satisfied when one or more of the checkboxes with that name in that form are checked.
For radio buttons, the required attribute shall only be satisfied when exactly one of the radio buttons in that radio group is checked.
am i doing something wrong, or is this a browser bug (on both chrome & ff) ??
You can make it with jQuery a less lines:
$(function(){
var requiredCheckboxes = $(':checkbox[required]');
requiredCheckboxes.change(function(){
if(requiredCheckboxes.is(':checked')) {
requiredCheckboxes.removeAttr('required');
}
else {
requiredCheckboxes.attr('required', 'required');
}
});
});
With $(':checkbox[required]') you select all checkboxes with the attribute required, then, with the .change method applied to this group of checkboxes, you can execute the function you want when any item of this group changes. In this case, if any of the checkboxes is checked, I remove the required attribute for all of the checkboxes that are part of the selected group.
I hope this helps.
Farewell.
Sorry, now I've read what you expected better, so I'm updating the answer.
Based on the HTML5 Specs from W3C, nothing is wrong. I created this JSFiddle test and it's behaving correctly based on the specs (for those browsers based on the specs, like Chrome 11 and Firefox 4):
<form>
<input type="checkbox" name="q" id="a-0" required autofocus>
<label for="a-0">a-1</label>
<br>
<input type="checkbox" name="q" id="a-1" required>
<label for="a-1">a-2</label>
<br>
<input type="checkbox" name="q" id="a-2" required>
<label for="a-2">a-3</label>
<br>
<input type="submit">
</form>
I agree that it isn't very usable (in fact many people have complained about it in the W3C's mailing lists).
But browsers are just following the standard's recommendations, which is correct. The standard is a little misleading, but we can't do anything about it in practice. You can always use JavaScript for form validation, though, like some great jQuery validation plugin.
Another approach would be choosing a polyfill that can make (almost) all browsers interpret form validation rightly.
To provide another approach similar to the answer by #IvanCollantes.
It works by additionally filtering the required checkboxes by name. I also simplified the code a bit and checks for a default checked checkbox.
jQuery(function($) {
var requiredCheckboxes = $(':checkbox[required]');
requiredCheckboxes.on('change', function(e) {
var checkboxGroup = requiredCheckboxes.filter('[name="' + $(this).attr('name') + '"]');
var isChecked = checkboxGroup.is(':checked');
checkboxGroup.prop('required', !isChecked);
});
requiredCheckboxes.trigger('change');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form target="_blank">
<p>
At least one checkbox from each group is required...
</p>
<fieldset>
<legend>Checkboxes Group test</legend>
<label>
<input type="checkbox" name="test[]" value="1" checked="checked" required="required">test-1
</label>
<label>
<input type="checkbox" name="test[]" value="2" required="required">test-2
</label>
<label>
<input type="checkbox" name="test[]" value="3" required="required">test-3
</label>
</fieldset>
<br>
<fieldset>
<legend>Checkboxes Group test2</legend>
<label>
<input type="checkbox" name="test2[]" value="1" required="required">test2-1
</label>
<label>
<input type="checkbox" name="test2[]" value="2" required="required">test2-2
</label>
<label>
<input type="checkbox" name="test2[]" value="3" required="required">test2-3
</label>
</fieldset>
<hr>
<button type="submit" value="submit">Submit</button>
</form>
i had the same problem, my solution was apply the required attribute to all elements
<input type="checkbox" name="checkin_days[]" required="required" value="0" /><span class="w">S</span>
<input type="checkbox" name="checkin_days[]" required="required" value="1" /><span class="w">M</span>
<input type="checkbox" name="checkin_days[]" required="required" value="2" /><span class="w">T</span>
<input type="checkbox" name="checkin_days[]" required="required" value="3" /><span class="w">W</span>
<input type="checkbox" name="checkin_days[]" required="required" value="4" /><span class="w">T</span>
<input type="checkbox" name="checkin_days[]" required="required" value="5" /><span class="w">F</span>
<input type="checkbox" name="checkin_days[]" required="required" value="6" /><span class="w">S</span>
when the user check one of the elements i remove the required attribute from all elements:
var $checkedCheckboxes = $('#recurrent_checkin :checkbox[name="checkin_days[]"]:checked'),
$checkboxes = $('#recurrent_checkin :checkbox[name="checkin_days[]"]');
$checkboxes.click(function() {
if($checkedCheckboxes.length) {
$checkboxes.removeAttr('required');
} else {
$checkboxes.attr('required', 'required');
}
});
Here is improvement for icova's answer. It also groups inputs by name.
$(function(){
var allRequiredCheckboxes = $(':checkbox[required]');
var checkboxNames = [];
for (var i = 0; i < allRequiredCheckboxes.length; ++i){
var name = allRequiredCheckboxes[i].name;
checkboxNames.push(name);
}
checkboxNames = checkboxNames.reduce(function(p, c) {
if (p.indexOf(c) < 0) p.push(c);
return p;
}, []);
for (var i in checkboxNames){
!function(){
var name = checkboxNames[i];
var checkboxes = $('input[name="' + name + '"]');
checkboxes.change(function(){
if(checkboxes.is(':checked')) {
checkboxes.removeAttr('required');
} else {
checkboxes.attr('required', 'required');
}
});
}();
}
});
A little jQuery fix:
$(function(){
var chbxs = $(':checkbox[required]');
var namedChbxs = {};
chbxs.each(function(){
var name = $(this).attr('name');
namedChbxs[name] = (namedChbxs[name] || $()).add(this);
});
chbxs.change(function(){
var name = $(this).attr('name');
var cbx = namedChbxs[name];
if(cbx.filter(':checked').length>0){
cbx.removeAttr('required');
}else{
cbx.attr('required','required');
}
});
});
Building on icova's answer, here's the code so you can use a custom HTML5 validation message:
$(function() {
var requiredCheckboxes = $(':checkbox[required]');
requiredCheckboxes.change(function() {
if (requiredCheckboxes.is(':checked')) {requiredCheckboxes.removeAttr('required');}
else {requiredCheckboxes.attr('required', 'required');}
});
$("input").each(function() {
$(this).on('invalid', function(e) {
e.target.setCustomValidity('');
if (!e.target.validity.valid) {
e.target.setCustomValidity('Please, select at least one of these options');
}
}).on('input, click', function(e) {e.target.setCustomValidity('');});
});
});
var verifyPaymentType = function () {
//coloque os checkbox dentro de uma div com a class checkbox
var inputs = window.jQuery('.checkbox').find('input');
var first = inputs.first()[0];
inputs.on('change', function () {
this.setCustomValidity('');
});
first.setCustomValidity( window.jQuery('.checkbox').find('input:checked').length === 0 ? 'Choose one' : '');
}
window.jQuery('#submit').click(verifyPaymentType);
}