{"id":372979,"date":"2022-09-08T06:12:51","date_gmt":"2022-09-08T13:12:51","guid":{"rendered":"https:\/\/css-tricks.com\/?p=372979"},"modified":"2022-09-08T06:12:52","modified_gmt":"2022-09-08T13:12:52","slug":"whats-new-with-forms-in-2022","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/whats-new-with-forms-in-2022\/","title":{"rendered":"What\u2019s New With Forms in 2022?"},"content":{"rendered":"\n

Browsers are constantly adding new HTML, JavaScript and CSS features. Here are some useful additions to working with forms that you might have missed\u2026<\/p>\n\n\n\n\n\n\n

requestSubmit()<\/code><\/h3>\n\n\n

Safari 16<\/a> will be the final browser to add support for requestSubmit<\/code>.<\/p>\n\n\n\n

Before we look at how .requestSubmit()<\/code> works, let\u2019s remind ourselves how programmatically submitting a form with JavaScript works when using the .submit()<\/code> method. Submitting a form with submit()<\/code> does not trigger a submit event. So in the following code, the form is submitted, preventDefault()<\/code> has no effect, and nothing is logged to the console:<\/p>\n\n\n\n

const form = document.forms[0];\nform.addEventListener('submit', function(event) {\n  \/\/ code to submit the form goes here\n  event.preventDefault();\n  console.log('form submitted!');\n});\n\ndocument.querySelector('.btn').addEventListener('click', function() {\n  form.submit();\n})<\/code><\/pre>\n\n\n\n

.submit()<\/code> will also ignore any HTML form validation. Given the following markup, the form will be submitted when the input is empty even though the input has a required<\/code> attribute:<\/p>\n\n\n\n

<form>   \n  <label for=\"name\">Name<\/label>\n  <input required name=\"name\" id=\"name\" type=\"text\">\n<\/form><\/code><\/pre>\n\n\n\n

.requestSubmit()<\/code> is an alternative way to submit a form using JavaScript, but in contrast to .submit()<\/code>, HTML form validation will prevent the form from being submitted. If all the data entered in the form passes validation, the submit<\/code> event will be fired, meaning \u201cform submitted!\u201d would be logged to the console in the following example:<\/p>\n\n\n\n

form.addEventListener('submit', function(event) {\n  event.preventDefault();\n  console.log('form submitted!');\n});\n\ndocument.querySelector('.btn').addEventListener('click', function() {\n  form.requestSubmit();\n})<\/code><\/pre>\n\n\n\n

You could already achieve this by programmatically clicking the form\u2019s submit button, but requestSubmit<\/code> is perhaps a more elegant solution.<\/p>\n\n\n

submitter<\/code> property of submit event<\/h3>\n\n\n

The SubmitEvent.submitter<\/code> property gained full cross-browser support<\/a> with the release of Safari 15.4. This read-only property specifies the <button><\/code> or <input type=\"submit\"><\/code> element that caused a form to be submitted.<\/p>\n\n\n\n

<form>\n  <button name=\"foo\" value=\"bar\" type=\"submit\">Bar<\/button>\n  <button name=\"foo\" value=\"baz\" type=\"submit\">Baz<\/button>\n<\/form><\/code><\/pre>\n\n\n\n

When you have multiple submit buttons or inputs, each with a different value, only the value of the button or input that was clicked on to submit the form will be sent to the server, rather than both values. That\u2019s nothing new. What is new is that the event listener for the submit event now has access to the event.submitter<\/code> property. You can use this to add a class to the button or input that triggered the form submission, for example, or to obtain its value<\/code> or any other of its HTML attributes.<\/p>\n\n\n\n

document.forms[0].addEventListener('submit', function(event) {\n  event.preventDefault();\n  console.log(event.submitter.value);\n  console.log(event.submitter.formaction);\n  event.submitter.classList.add('spinner-animation');\n})<\/code><\/pre>\n\n\n

formdata<\/code> event<\/h3>\n\n\n

This isn\u2019t particularly new, but only achieved cross-browser support<\/a> with the release of Safari 15. The main use case for the formdata<\/code> event is enabling custom elements to take part in form submissions. Outside of web components, though, it can still be useful.<\/p>\n\n\n\n

You add a formdata<\/code> event listener to the form you want to interact with:<\/p>\n\n\n\n

document.querySelector('form').addEventListener('formdata', handleFormdata);<\/code><\/pre>\n\n\n\n

The event is fired both by a regular HTML form submission and also by an occurrence of new FormData()<\/code>. event.formData<\/code> holds all of the data being submitted.<\/p>\n\n\n\n

function handleFormdata(event) {\n  for (const entry of event.formData.values()) {\n    console.log(entry);\n  }\n}<\/code><\/pre>\n\n\n\n

The callback function for the formdata<\/code> event listener runs before the data is sent to the server, giving you a chance to add to or modify the data being sent.<\/p>\n\n\n\n

function handleFormdata(event) {\n  event.formData.append('name', 'John');\n}<\/code><\/pre>\n\n\n\n

You could have modified or appended the FormData<\/code> inside the submit event handler but formdata<\/code> allows you to separate out the logic. It\u2019s also an alternative to using hidden inputs in the markup of your form in cases where you are submitting the form \u201cthe old fashioned way\u201d \u2014 i.e. relying on the built-in functionality of HTML to submit the form rather than doing it with fetch<\/code>.<\/p>\n\n\n

showPicker()<\/code> for input elements<\/h3>\n\n\n

showPicker()<\/code> has been supported<\/a> since Chrome 99, Firefox 101, and in the upcoming Safari 16. For an input element whose type attribute is either Date, Month, Week, Time, datetime-local<\/code>, color, or file, showPicker()<\/code> provides a programmatic way to display the selection UI. For color and file inputs, it\u2019s always been possible to programmatically show the picker by calling .click<\/code> on the input:<\/p>\n\n\n\n

document.querySelector('input[type=\"color\"]').click();<\/code><\/pre>\n\n\n\n

That approach doesn\u2019t work on date inputs, which is why this new API was added. .showPicker()<\/code> will also work with color and file inputs but there\u2019s no real advantage to using it over .click()<\/code>.<\/p>\n\n\n\n

\"Datepicker<\/figure>\n\n\n

Inert attribute<\/h3>\n\n\n

It\u2019s always been possible to disable multiple inputs at once by wrapping them in a HTML fieldset<\/code> and disabling the fieldset<\/code>:<\/p>\n\n\n\n