Разное

Контактная форма js: Создаем аккуратную контактную форму на HTML5

10.07.2023

Работа с формами — JavaScript — Дока

Кратко

Скопировано

Помимо стандартных средств работы с формами можно использовать JavaScript, чтобы проверять формы на валидность, получать доступ к значениям и отправлять информацию на сервер.

Трюки для работы с формами в JS проще всего показать на примере. В этой статье мы соберём форму заявки на участие в миссии по колонизации Марса. В этой форме мы немножко приправим стандартные HTML-атрибуты динамикой на JS.

Разметка и требования

Скопировано

Наша форма заявки на участие в миссии «Mars Once» будет состоять из шести полей. В форме мы собираем следующие данные:

  • Имя, чтобы знать, как обращаться в ответном письме.
  • Почту, чтобы знать, куда это письмо слать.
  • Возраст — нужны только молодые 🤷‍♂️
  • Специализацию — инженеры и учёные пригодятся для основной работы, а психологи нужны, чтобы команда друг друга не перегрызла за десятилетнюю колонизаторскую миссию.
  • Работал ли человек в NASA — это большой плюс.
  • Фотография, чтобы использовать в печатных материалах.
<form action="/apply/" method="POST">  <label>    Ваше имя:    <input type="text" name="name" placeholder="Илон Маск" required autofocus>  </label>  <label>    Почта:    <input type="email" name="email" placeholder="[email protected]" required>  </label>  <label>    Возраст:    <input type="number" name="age" required>  </label>  <label>    Профессия:    <select name="specialization" required>      <option value="engineer" selected>Инженер</option>      <option value="scientist">Учёный</option>      <option value="psychologist">Психолог</option>      <option value="other">Другая</option>    </select>  </label>  <label>    Я работал в NASA    <input type="checkbox" name="nasa-experience" value="1">  </label>  <label>    Фото:    <input type="file" accept="image/jpeg" name="photo" required>  </label>  <button type="submit">Отправить заявку</button></form>
          
<form action="/apply/" method="POST"> <label> Ваше имя: <input type="text" name="name" placeholder="Илон Маск" required autofocus> </label> <label> Почта: <input type="email" name="email" placeholder="elon@musk.
com" required> </label> <label> Возраст: <input type="number" name="age" required> </label> <label> Профессия: <select name="specialization" required> <option value="engineer" selected>Инженер</option> <option value="scientist">Учёный</option> <option value="psychologist">Психолог</option> <option value="other">Другая</option> </select> </label> <label> Я работал в NASA <input type="checkbox" name="nasa-experience" value="1"> </label> <label> Фото: <input type="file" accept="image/jpeg" name="photo" required> </label> <button type="submit">Отправить заявку</button> </form>
Открыть демо в новой вкладке

В целом форма рабочая: обязательные поля не пропустят пустые значения, атрибут type проследит, чтобы вместо почты нам не прислали номер телефона, а по нажатию на кнопку валидная форма отправит все данные.

Но нам кроме всего этого хочется:

  • чтобы страница при отправке не перезагружалась;
  • чтобы во время запроса показывался лоадер, при успешной отправке — поздравление, а при ошибке — причина ошибки;
  • чтобы кнопка была заблокирована до тех пор, пока форма не валидна.

Приступим.

Отправка без перезагрузки

Скопировано

Первым делом настроим отправку формы без перезагрузки страницы.

Перезагрузка страницы — это поведение по умолчанию для отправки формы. Чтобы его предотвратить, нам нужно «перехватить» управление в момент отправки и сказать форме, что делать вместо этого.

Предотвращаем отправку данных

Скопировано

Для «предотвращения» срабатывания событий мы можем использовать метод preventDefault()

на объекте события. В нашем случае событием будет отправка формы — submit.

Если наше событие находится в переменной event, то для предотвращения поведения по умолчанию мы можем вызвать event. preventDefault().

Чтобы «соединить» форму с нашей будущей собственной отправкой данных, мы напишем функцию, которая будет «слушать» событие отправки и реагировать на него.

Найдём форму на странице, с помощью getElementById и подпишемся на событие submit с помощью

addEventListener. Пока мы не будем отправлять форму, а просто напечатаем в консоль строку «Отправка!» и убедимся, что механизм работает:

function handleFormSubmit(event) {  // Просим форму не отправлять данные самостоятельно  event.preventDefault()  console.log('Отправка!')}const applicantForm = document.getElementById('mars-once')applicantForm.addEventListener('submit', handleFormSubmit)
          function handleFormSubmit(event) {
  // Просим форму не отправлять данные самостоятельно
  event.preventDefault()
  console.log('Отправка!')
}
const applicantForm = document.
getElementById('mars-once') applicantForm.addEventListener('submit', handleFormSubmit)

Мы можем просто передать функцию handleFormSubmit() как второй аргумент в addEventListener(), так как он автоматически передаст событие в качестве аргумента для handleFormSubmit().

Получится, что при отправке формы сработает событие submit, которое запустит наш обработчик handleFormSubmit()

.

В этот обработчик как аргумент event будет передано событие отправки. Мы вызовем event.preventDefault(), и форма не отправится самостоятельно.

Собираем данные из формы

Скопировано

Следующий шаг — собрать всё, что необходимо отправить.

Нам не хочется собирать каждое значение отдельно.

  • Это может быть долго: если форма состоит из 10 полей, это уже требует достаточно много кода.
  • Это не масштабируется: если мы захотим добавить ещё пару полей, нам придётся писать код и для этих полей тоже.

Вместо этого мы будем использовать возможности языка, чтобы достать все поля и элементы управления из формы. Напишем функцию serializeForm:

function serializeForm(formNode) {  console.log(formNode.elements)}function handleFormSubmit(event) {  event.preventDefault()  serializeForm(applicantForm)}const applicantForm = document.getElementById('mars-once')applicantForm.addEventListener('submit', handleFormSubmit)
          function serializeForm(formNode) {
  console.log(formNode.elements)
}
function handleFormSubmit(event) {
  event.preventDefault()
  serializeForm(applicantForm)
}
const applicantForm = document.getElementById('mars-once')
applicantForm.addEventListener('submit', handleFormSubmit)

Аргумент функции serializeForm — это элемент формы. Именно элемент — не селектор, а конкретный узел в DOM-дереве.

У форм есть свойство elements, которое содержит в себе все элементы управления и поля этой формы. Именно этим свойством мы воспользуемся, чтобы получить все данные из формы.

Если сейчас мы вызовем эту функцию, передав туда нашу форму как аргумент, то в консоли появится список всех элементов:

HTMLFormControlsCollection
  0 <input type="text" name="name" placeholder="Илон Маск" autofocus>
  1 <input type="email" name="email" placeholder="[email protected]">
  2 <input type="number" name="age">
  3 <select name="specialization">
  4 <input type="checkbox" name="nasa-experience" value="1">
  5 <input type="file" accept="image/jpeg" name="photo">
  6 <button type="submit">Отправить заявку</button>

Обратите внимание, что тип этого набора элементов — HTMLFormControlsCollection. Это не массив и, чтобы пройтись циклом по списку элементов, нужно превратить его в массив с помощью вызова

Array. from().

Нам останется собрать имя и значение каждого из полей. Для начала, выведем имя и значение каждого элемента в консоль:

function serializeForm(formNode) {  const { elements } = formNode  Array.from(elements)    .forEach((element) => {      const { name, value } = element      console.log({ name, value })    })}
          function serializeForm(formNode) {
  const { elements } = formNode
  Array.from(elements)
    .forEach((element) => {
      const { name, value } = element
      console.log({ name, value })
    })
}

Мы получили список элементов, преобразовали его в массив и прошлись по каждому элементу. У каждого элемента получили поля name и value и вывели их в консоль.

В консоли после запуска получим вывод по каждому из полей:

1 {name: 'name', value: 'Alex'}
2 {name: 'email', value: '[email protected]'}
3 {name: 'age', value: '24'}
4 {name: 'specialization', value: 'engineer'}
5 {name: 'nasa-experience', value: '1'}
6 {name: 'photo', value: 'C:\\fakepath\\image. jpg'}
7 {name: '', value: ''}

Заметим, что последняя строчка не имеет ни названия, ни значения. Это потому, что последний элемент, который мы проверяли — это кнопка.

Чтобы элементы без названия нам не мешались, мы отфильтруем наш набор. Воспользуемся методом filter, чтобы отбросить элементы с пустым именем. Также заменим метод forEach на map — он соберёт нам массив, который хранит объект с именем и значением каждого отфильтрованного элемента.

function serializeForm(formNode) {  const { elements } = formNode  const data = Array.from(elements)    .filter((item) => !!item.name)    .map((element) => {      const { name, value } = element      return { name, value }    })  console.log(data)}
          function serializeForm(formNode) {
  const { elements } = formNode
  const data = Array.from(elements)
    .filter((item) => !!item.name)
    .map((element) => {
      const { name, value } = element
      return { name, value }
    })
  console. log(data)
}

На выходе в консоли получится массив из объектов с name и value:

[  {name: 'name', value: 'Alex'},  {name: 'email', value: '[email protected]'},  {name: 'age', value: '24'},  {name: 'specialization', value: 'engineer'},  {name: 'nasa-experience', value: '1'},  {name: 'photo', value: 'C:\\fakepath\\image.jpg'}]
          [
  {name: 'name', value: 'Alex'},
  {name: 'email', value: '[email protected]'},
  {name: 'age', value: '24'},
  {name: 'specialization', value: 'engineer'},
  {name: 'nasa-experience', value: '1'},
  {name: 'photo', value: 'C:\\fakepath\\image.jpg'}
]

Значения чекбоксов

Скопировано

Сейчас можно заметить, что nasa-experience имеет значение "1". Это неправильно:

  • мы не отмечали чекбокс, а значение почему-то "1";
  • в целом хотелось бы, чтобы значение этого поля было булевым.

Для этого мы можем использовать особое свойство checked, которое есть у чекбоксов.

const isOn = someCheckboxInput.checked
          const isOn = someCheckboxInput.checked

Значение этого поля как раз булево, и мы можем использовать это в нашей функции serializeForm.

Но это свойство мы хотим использовать только на чекбоксе, а не на остальных полях. Это тоже можно сделать. Прочитаем тип элемента и, если он "checkbox", то возьмём в качестве значения поле checked:

function serializeForm(formNode) {  const { elements } = formNode  const data = Array.from(elements)    .map((element) => {      const { name, type } = element      const value = type === 'checkbox' ? element.checked : element.value      return { name, value }    })    .filter((item) => !!item.name)  console.log(data)}
          function serializeForm(formNode) {
  const { elements } = formNode
  const data = Array.from(elements)
    .map((element) => {
      const { name, type } = element
      const value = type === 'checkbox' ? element. checked : element.value
      return { name, value }
    })
    .filter((item) => !!item.name)
  console.log(data)
}

Теперь значение поля nasa-experience будет true, если чекбокс отмечен, и false, если пропущен. Увидим такой вывод:

[  {name: 'name', value: 'Alex'},  {name: 'email', value: '[email protected]'},  {name: 'age', value: '24'},  {name: 'specialization', value: 'engineer'},  {name: 'nasa-experience', value: false},  {name: 'photo', value: 'C:\\fakepath\\image.jpg'}]
          [
  {name: 'name', value: 'Alex'},
  {name: 'email', value: '[email protected]'},
  {name: 'age', value: '24'},
  {name: 'specialization', value: 'engineer'},
  {name: 'nasa-experience', value: false},
  {name: 'photo', value: 'C:\\fakepath\\image.jpg'}
]

Формат данных

Скопировано

В целом, нынешний формат данных в виде массива объектов нам может и подойти, но мы с вами используем кое-что лучше — FormData.

FormData — это особый тип данных, который можно использовать для отправки данных формы на сервер.

Мы воспользуемся им, чтобы сохранить данные из формы. Создадим экземпляр с помощью new FormData(), откажемся от массива со значениями и будем добавлять имена полей и их значения в FormData с помощью вызова функции append:

function serializeForm(formNode) {  const { elements } = formNode  const data = new FormData()  Array.from(elements)    .filter((item) => !!item.name)    .forEach((element) => {      const { name, type } = element      const value = type === 'checkbox' ? element.checked : element.value      data.append(name, value)    })  return data}
          function serializeForm(formNode) {
  const { elements } = formNode
  const data = new FormData()
  Array.from(elements)
    .filter((item) => !!item.name)
    .forEach((element) => {
      const { name, type } = element
      const value = type === 'checkbox' ? element. checked : element.value
      data.append(name, value)
    })
  return data
}

Но так как тип FormData специально создан для работы с формами, можно сделать гораздо проще 🙂

function serializeForm(formNode) {  return new FormData(formNode)}
          function serializeForm(formNode) {
  return new FormData(formNode)
}

Стоит отметить, что nasa-experience в таком случае попадёт в финальные данные, только если чекбокс отметили. Если его не отметить, то в финальных данных он не окажется.

Когда чекбокс nasa-experience выделен, получим такой вывод:

[  ['name', 'Alex'],  ['email', '[email protected]'],  ['age', '24'],  ['specialization', 'engineer'],  ['nasa-experience', '1'],  ['photo', File],]
          [
  ['name', 'Alex'],
  ['email', '[email protected]'],
  ['age', '24'],
  ['specialization', 'engineer'],
  ['nasa-experience', '1'],
  ['photo', File],
]

Когда чекбокс не выделен — такой:

[  ['name', 'Alex'],  ['email', 'example@test. com'],  ['age', '24'],  ['specialization', 'engineer'],  ['photo', File],]
          [
  ['name', 'Alex'],
  ['email', '[email protected]'],
  ['age', '24'],
  ['specialization', 'engineer'],
  ['photo', File],
]

В первом случае чекбокс был отмечен, поэтому в списке есть элемент nasa-experience, во втором случае чекбокс был пропущен, поэтому такого элемента в списке данных нет.

Чтобы проверить, какие данные в себе содержит переменная типа FormData, можно использовать метод .entries(), он выведет список с данными, как в примере выше.

console.log(Array.from(data.entries()))
          console.log(Array.from(data.entries()))

Отправка на сервер

Скопировано

Теперь нам надо данные из формы отправить на сервер. Представим, что наш бэкенд предоставляет API-эндпоинт для сохранения данных. Попробуем отправить их.

Функция будет асинхронной, потому что работает с сетевыми запросами. В качестве аргумента она принимает FormData и отправляет запрос с помощью вызова fetch. Нам нужно указать правильный заголовок Content-Type у запроса, для формы он 'multipart/form-data':

async function sendData(data) {  return await fetch('/api/apply/', {    method: 'POST',    headers: { 'Content-Type': 'multipart/form-data' },    body: data,  })}
          async function sendData(data) {
  return await fetch('/api/apply/', {
    method: 'POST',
    headers: { 'Content-Type': 'multipart/form-data' },
    body: data,
  })
}

Функция вернёт результат запроса к серверу, который мы сможем проверить на ошибки.

Теперь используем эту функцию в обработчике события отправки. Сериализуем форму и передадим её в функцию отправки. Вместо обращения напрямую к форме, будем читать её из объекта события. Форма в объекте события submit будет храниться в свойстве target:

async function handleFormSubmit(event) {  event. preventDefault()  const data = serializeForm(event.target)  const response = await sendData(data)}
          async function handleFormSubmit(event) {
  event.preventDefault()
  const data = serializeForm(event.target)
  const response = await sendData(data)
}

Обратите внимание, что функция handleFromSubmit() стала асинхронной, так как она вызывает другую асинхронную функцию и дожидается её результата. Внутри response будет поле status, по которому мы сможем определить, успешно ли прошёл запрос и вывести соответствующее сообщение пользователю.

Обработка загрузки и вывод сообщения о результате

Скопировано

Теперь немножко улучшим UX нашей формы. Сейчас она просто отправляет данные и ничего не сообщает пользователям. Это не круто, потому что отправителю будет непонятно, получилось ли записаться в «Mars Once» или нет.

Мы хотим:

  • при отправке формы показывать лоадер, пока идёт запрос;
  • при успешной отправке показать сообщение, что форма отправлена, и спрятать форму;
  • при ошибке указать пользователю, где именно была ошибка.

Начнём с лоадера.

Показываем лоадер во время отправки

Скопировано

У нас вместо лоадера будет просто показываться строка «Sending…»

Добавим его после кнопки и спрячем:

<style>  .hidden {    display:none;  }</style><form action="/apply/" method="POST">  <!-- Код остальной формы -->  <button type="submit">Отправить заявку</button>  <div>Отправляем...</div></form>
          <style>
  .hidden {
    display:none;
  }
</style>
<form action="/apply/" method="POST">
  <!-- Код остальной формы -->
  <button type="submit">Отправить заявку</button>
  <div>Отправляем...</div>
</form>

Прячем мы его, потому что хотим показать только во время запроса. Для этого напишем функцию, которые будут управлять его состоянием — делать лоадер видимым, если он не виден сейчас, и скрывать, если он виден. Так как технически это добавление и удаление класса hidden, то можно воспользоваться функцией toggle из classList API:

function toggleLoader() {  const loader = document. getElementById('loader')  loader.classList.toggle('hidden')}
          function toggleLoader() {
  const loader = document.getElementById('loader')
  loader.classList.toggle('hidden')
}

Вызовем эту функцию до отправки запроса, чтобы показать лоадер, и после запроса, чтобы скрыть. Лоадер будет виден до тех пор, пока запрос не завершится:

async function handleFormSubmit(event) {  event.preventDefault()  const data = serializeForm(event.target)  toggleLoader()  const response = await sendData(data)  toggleLoader()}
          async function handleFormSubmit(event) {
  event.preventDefault()
  const data = serializeForm(event.target)
  toggleLoader()
  const response = await sendData(data)
  toggleLoader()
}

Обрабатываем успешную отправку

Скопировано

Давайте теперь проверять ответ сервера. Допустим, нам хочется, чтобы при успешной отправке мы показывали alert() с сообщением об успешной отправке и прятали форму:

function onSuccess(formNode) {  alert('Ваша заявка отправлена!')  formNode. classList.toggle('hidden')}
          function onSuccess(formNode) {
  alert('Ваша заявка отправлена!')
  formNode.classList.toggle('hidden')
}

Мы должны вызвать onSuccess, только если форма была отправлена успешна. Для этого добавим проверку на статус ответа сервера — он должен быть 200 в случае успеха (статусы ответа разобраны в статье про HTTP протокол):

// Вызовем её вот так:async function handleFormSubmit(event) {  event.preventDefault()  const data = serializeForm(event.target)  toggleLoader()  const { status } = await sendData(data)  toggleLoader()  if (status === 200) {    onSuccess(event.target)  }}
          // Вызовем её вот так:
async function handleFormSubmit(event) {
  event.preventDefault()
  const data = serializeForm(event.target)
  toggleLoader()
  const { status } = await sendData(data)
  toggleLoader()
  if (status === 200) {
    onSuccess(event.target)
  }
}

При успешной отправке покажется это сообщение, а форма пропадёт.

Обрабатываем ошибки

Скопировано

Если что-то пошло не так, то мы хотим сказать пользователям об этом. Напишем функцию, которая будет вызывать alert() с сообщением, которое пришлёт сервер в случае ошибки:

function onError(error) {  alert(error.message)}
          function onError(error) {
  alert(error.message)
}

Мы могли бы вызвать alert сразу на месте, но лучше вынести обработку ошибки в отдельную функцию. Так, если нам захочется добавить какие-то действия по обработке ошибок, нам будет проще ориентироваться в коде.

Вместе со статусом будем получать информацию об ошибке из поля error. Если запрос был успешным, то error будет пустым, но в случае ошибки там будет лежать сообщение:

async function handleFormSubmit(event) {  event.preventDefault()  const data = serializeForm(event.target)  toggleLoader()  const { status, error } = await sendData(data)  toggleLoader()  if (status === 200) {    onSuccess(event. target)  } else {    onError(error)  }}
          async function handleFormSubmit(event) {
  event.preventDefault()
  const data = serializeForm(event.target)
  toggleLoader()
  const { status, error } = await sendData(data)
  toggleLoader()
  if (status === 200) {
    onSuccess(event.target)
  } else {
    onError(error)
  }
}

Если что-то пошло не так, мы увидим причину. Форма останется на месте.

Блокируем кнопку отправки на невалидной форме

Скопировано

Сейчас кнопку отправки можно нажать в любой момент, даже если форма невалидна. И хоть пользователь не сможет отправить форму из-за HTML-валидации, было бы неплохо предупредить, что кнопку нажимать пока рано.

Давайте будем её блокировать до тех пор, пока не будут заполнены все поля, которые требуется заполнить.

Напишем функцию, которая будет проверять валидность формы и блокировать кнопку, если требуется. Аргументом она будет принимать событие ввода с клавиатуры на полях ввода.

Так как событие ввода будет происходить на полях, а не на самой форме, то значение event. target — это поле. Чтобы получить форму, воспользуемся свойством form, значением которого является ссылка на родительскую форму.

Проверять валидность формы будем с помощью метода checkValidity() формы. Он запускает стандартные проверки. Результат проверки будем использовать, для того чтобы установить свойство disabled кнопки в значение true, если нужно заблокировать, и false, если кнопка должна быть доступна.

function checkValidity(event) {  const formNode = event.target.form  const isValid = formNode.checkValidity()  formNode.querySelector('button').disabled = !isValid}applicantForm.addEventListener('input', checkValidity)
          function checkValidity(event) {
  const formNode = event.target.form
  const isValid = formNode.checkValidity()
  formNode.querySelector('button').disabled = !isValid
}
applicantForm.addEventListener('input', checkValidity)

Теперь, пока форма не будет заполнена, кнопка будет заблокирована.

Что у нас получилось

Скопировано

Мы сделали форму, которая отправляет данные без перезагрузки страницы, показывает сообщение об ошибке или успешной отправке и блокирует кнопку, пока не введены значения.

Для всего этого мы использовали методы HTML-элементов и элементов форм, которые нам предоставляет браузер и веб-платформа.

Конечно, этим работа с формами не заканчивается. Ещё можно сделать валидацию каждого поля в отдельности, загрузку картинок с возможностью их редактирования, добавить всякие комбо-боксы и нестандартные элементы.

Но для первой формы, с которой мы работали в JS, этого достаточно 🙂

HTML5 | Формы

184

Веб-программирование — HTML5 — Формы

HTML-формы — это простые элементы управления HTML, которые применяются для сбора информации от посетителей веб-сайта. К ним относятся текстовые поля для ввода данных с клавиатуры, списки для выбора предопределенных данных, флажки для установки параметров и т. п. Существует бесчисленное количество способов использования HTML-форм, и если вы побродили по просторам Интернета всего лишь несколько дней, то, несомненно, использовали их для разных целей — от регистрации на каком-либо форуме или получения почтового ящика до просмотра биржевого курса или покупки товара в интернет-магазине.

HTML-формы существовали с самых ранних времен языка HTML, и с тех пор они нисколько не изменились, несмотря на определенные серьезные усилия. Разработчики веб-стандартов несколько лет колдовали над стандартом XForms, который должен был заменить HTML-формы, но его постиг такой же провал, как и стандарт XHTML 2.

Хотя стандарт XForms позволял легко и элегантно решать некоторые задачи, он также имел и значительные недостатки. Например, код XForms был очень объемистый, и для работы с ним нужно хорошее знание стандарта XML. Но самое большое препятствие состояло в том, что стандарт XForms не был совместим с HTML-формами ни в каких отношениях. Это означало, что разработчикам нужно было бы бросаться в неизведанные воды новой модели без вспомогательных плавсредств, а лишь со слепой верой и огромным мужеством.

Но так как разработчики основных браузеров никогда не заморачивались с реализацией XForms в своих продуктах по причине его слишком большой сложности и небольшого использования, сообщество веб-разработчиков так никогда и не сделало этот прыжок.

Стандарт HTML5 предлагает другой подход. Вместо того чтобы начинать с нуля, как в XForms, он совершенствует уже существующую модель HTML-форм. Это означает, что HTML5-формы могут работать и на старых браузерах, лишь без новых примочек и наворотов. HTML5-формы также позволяют применять новые возможности, которые уже используются разработчиками в настоящее время. Эти возможности более доступны, не требуют написания страниц сценариев JavaScript или применения инструментариев JavaScript сторонних разработчиков.

Что такое форма?

Скорее всего, вам приходилось работать с формами раньше. Но если нет или вы порядочно подзабыли эту тему, следующий материал позволит вам получить необходимые сведения для более углубленного изучения этой области веб-дизайна.

Веб-форма — это набор текстовых полей, списков, кнопок и других активизируемых щелчком мыши элементов управления, посредством которых посетитель страницы может предоставить ей тот или иной вид информации. Формы в Интернете повсюду — благодаря формам мы можем создавать учетные записи электронной почты, просматривать и покупать товары в интернет-магазинах, осуществлять финансовые транзакции и многое другое. Самая простая форма — это одинокое текстовое поле поисковых систем, таких как Google:

Все основные веб-формы работают одинаково. Пользователь вводит определенную информацию, а потом нажимает кнопку, чтобы отправить введенную информацию на веб-сервер. По прибытию на веб-сервер эта информация обрабатывается каким-либо приложением, которое потом предпринимает соответствующий очередной шаг. Перед тем как отослать новую страницу назад браузеру, серверная программа может обратиться к базе данных, чтобы извлечь или сохранить информацию.

Сложность этого процесса состоит в том, что существуют сотни разных способов реализации серверного приложения, которое обрабатывает поступившие из формы данные. Некоторым разработчикам может быть достаточно элементарных сценариев для манипулирования полученными данными, в то время как другие могут использовать средства высшего уровня, которые упаковывают данные из формы в аккуратные программные объекты. Но в любом случае, задача перед этими приложениями стоит, по большому счету, одинаковая — исследовать данные из формы, выполнить какие-либо действия с ними, а потом на основе полученных результатов отправить браузеру новую страницу.

Модернизация традиционной HTML-формы

Лучший способ обучения работе с формами HTML5 — это взять типичную современную форму и усовершенствовать ее. Ниже показана форма, на примере которой мы будем обучаться. Разметка такой формы до предела проста. Если вам раньше приходилось работать с формами, вы не увидите здесь ничего нового. Прежде всего, весь код формы заключается в элемент <form>.

Элемент <form> удерживает вместе все элементы управления формы, которые также называются полями. Кроме этого, он также указывает браузеру, куда отправить данные после нажатия пользователем кнопки отправки, предоставляя URL в атрибуте action. Но если вся работа будет выполняться на стороне клиента сценариям JavaScript, то для атрибута action можно просто указать значение #.

Хорошо спроектированная форма разделяется на логические фрагменты с помощью элемента <fieldset>. Каждому разделу можно присвоить название, для чего используется элемент <legend>. В следующем листинге приводится разметка формы:

<form action="#">
  <p><i>Пожалуйста, заполните форму. Обязательные поля помечены </i><em>*</em></p>
  <fieldset>
    <legend>Контактная информация</legend>
      <label for="name">Имя <em>*</em></label>
      <input><br>
      <label for="telephone">Телефон</label>
      <input><br>
      <label for="email">Email <em>*</em></label>
      <input><br>
  </fieldset>
  <fieldset>
    <legend>Персональная информация</legend>
      <label for="age">Возраст<em>*</em></label>
      <input><br>
      <label for="gender">Пол</label>
      <select>
        <option value="female">Женщина</option>
        <option value="male">Мужчина</option>
      </select><br>
      <label for="comments">Перечислите личные качества</label>
      <textarea></textarea>
  </fieldset>

  <fieldset>
    <legend>Выберите ваших любимых животных</legend>
    <label for="zebra"><input type="checkbox"> Зебра</label>
    <label for="cat"><input type="checkbox"> Кошак</label>
    <label for="anaconda"><input type="checkbox"> Анаконда</label>
    <label for="human"><input type="checkbox"> Человек</label>
    <label for="elephant"><input type="checkbox"> Слон</label>
    <label for="wildebeest"><input type="checkbox"> Антилопа</label>
    <label for="pigeon"><input type="checkbox"> Голубь</label>
    <label for="crab"><input type="checkbox"> Краб</label>
  </fieldset>
  <p><input type="submit" value="Отправить информацию"></p>
</form>

Добавьте немного стилей CSS:

body {
  font-family: 'Palatino Linotype', serif;
  max-width: 600px;
  padding: 0px 30px;
}

h2 {
  margin-bottom: 0px;
}

p {
  margin-top: 0px;
}

fieldset {
  margin-bottom: 15px;
  padding: 10px;
}

legend {
  padding: 0px 3px;
  font-weight: bold;
  font-variant: small-caps;
}

label {
  width: 110px;
  display: inline-block;
  vertical-align: top;
  margin: 6px;
}

em {
  font-weight: bold;
  font-style: normal;
  color: #f00;
}

input:focus {
  background: #eaeaea;
}

input, textarea {
  width: 249px;
}

textarea {
  height: 100px;
}

select {
  width: 254px;
}

input[type=checkbox] {
  width: 10px;
}

input[type=submit] {
  width: 170px;
  padding: 10px;
}

И вот результат:

Как и во всех формах, большая часть работы в нашем примере выполняете универсальным элементом <input>, который собирает данные и создает флажки, переключатели и списки. Для ввода одной строки текста применяется элемент <input>, а для нескольких — элемент <textarea>; элемент <select> создает выпадающий список. Краткое обозрение этих и других элементов управления форм приведено в таблице:

Элементы управления формы
Элемент управления HTML-элемент Описание
Однострочное текстовое поле <input type=»text»>
<input type=»password»>
Выводит однострочное текстовое поле для ввода текста. Если для атрибута type указано значение password, вводимые пользователем символы отображаются в виде звездочек (*) или маркеров-точек (•)
Многострочное текстовое поле <textarea>…</textarea> Текстовое поле, в которое можно ввести несколько строчек текста
Флажок <input type=»checkbox»> Выводит поле флажка, который можно установить или очистить
Переключатель <input type=»radio»> Выводит переключатель — элемент управления в виде небольшого кружка, который можно включить или выключить. Обычно создается группа переключателей с одинаковым значением атрибута name, вследствие чего можно выбрать только один из них
Кнопка <input type=»submit»>
<input type=»image»>
<input type=»reset»>
<input type=»button»>
Выводит стандартную кнопку, активизируемую щелчком мыши. Кнопка типа submit всегда собирает информацию с формы и отправляет ее для обработки. Кнопка типа image делает то же самое, но позволяет вместо текста на кнопке вставить изображение. Кнопка типа reset очищает поля формы от введенных пользователем данных. А кнопка типа button сама по себе не делает ничего. Чтобы ее нажатие выполняло какое-либо действие, для нее нужно добавить сценарий JavaScript
Список <select>…</select> Выводит список, из которого пользователь может выбирать значения. Для каждого значения списка добавляем элемент <option>

Одним из ограничений HTML-форм является то, что разработчик не может контролировать каким способом браузер отображает элементы управления формы. Например, если вы хотите заменить унылое серое поле флажка большим черно-белым полем с жирной красной галочкой, вам этого не удастся. (Одно из решений этой проблемы — создать с помощью JavaScript элемент с поведением, подобным флажку, иными словами, элемент меняет свой внешний вид, когда на нем щелкают.)

Это ограничение сохранилось и в HTML5 и распространяется на все новые элементы управления, которые мы рассмотрим. Это означает, что формы не подойдут для разработчиков, которым нужен полный контроль над внешним видом своих страниц в общем и требуются элементы управления с особым внешним видом в частности.

Теперь, когда у нас есть форма, с которой можно работать, настало время улучшить ее с помощью HTML5. Начнем мы это в следующих разделах с добавления подстановочного текста подсказок и поля с автоматическим фокусом.

Добавление подсказок

Обычно поля новой формы не содержат никаких данных. Для некоторых пользователей такая форма может быть не совсем понятной, в частности, какую именно информацию нужно вводить в конкретное поле. Поэтому часто поля формы содержат пример данных, которые нужно ввести в них. Этот подстановочный текст также называется «водяным знаком», так как он часто отображается шрифтом светло-серого цвета, чтобы отличить его от настоящего, введенного содержимого. Пример такого подстановочного текста показан на рисунке:

Вверху, когда поле пустое, в нем отображается подстановочный текст. Внизу, когда пользователь щелкает мышью в поле (устанавливая в нем фокус), подстановочный текст исчезает. Если пользователь переходит в другое поле, не введя ничего в первое, то поле снова заполняется подстановочным текстом.

Подстановочный текст для поля создается с помощью атрибута placeholder:

<input placeholder="Иван Иванов">
  ...
<input placeholder="+7 (xxx) xxx-xxxx">

Браузеры, не поддерживающие подстановочный текст, просто не обращают внимания на атрибут placeholder; особенно грешит этим Internet Explorer. К счастью, это не такая уж и большая проблема, т. к. подстановочный текст — всего лишь приятная примочка, не обязательная для функционирования формы.

В настоящее время не существует стандартного, единообразного способа изменить внешний вид подстановочного текста, например, выделить его курсивом или шрифтом определенного цвета. Со временем разработчики браузеров создадут требуемые для этого обработчики. Но пока либо нужно применять специфические для браузера CSS-псевдоклассы (а именно -webkit-input-placeholder и -moz-placeholder), либо смириться с таким порядком вещей.

А вот псевдокласс focus обеспечивается лучшей поддержкой, и его можно использовать, чтобы изменять внешний вид текстового поля при получении фокуса. Например, сделать фон поля более темным, чтобы оно выделялось среди остальных, можно следующим образом:

input:focus {
  background: #eaeaea;
}

Фокус

Так как форма предназначена для ввода информации, первым делом после ее загрузки пользователи захотят вводить эту информацию. К сожалению, делать это они не смогут до тех пор, пока не щелкнут мышью по первому полю или выделят его с помощью клавиши <Tab>, установив, таким образом, фокус на этом поле.

Пользователю можно помочь в этом, установив фокус на нужном начальном поле автоматически. Это можно сделать с помощью JavaScript, вызывая метод focus() требуемого элемента <input>. Но этот подход требует лишней строки кода и иногда может вызывать раздражающие неувязки.

Например, особо проворные пользователи могут опередить вызов метода focus(), щелкнуть в каком-либо другом поле и начать вводить в нем, а когда метод, наконец, вызовется, пользователь грубо выдвинется из выбранного им поля и переместится в поле, выбранное методом. Но если управлять фокусом может браузер, он может быть несколько более смышленым и перемещать фокус только в том случае, если пользователь еще не выбрал другое поле.

На этой идее основан новый HTML5-атрибут autofocus, который можно вставить в элемент <input> или <textarea> (но только в один элемент формы), как показано в следующем примере:

<input placeholder="Иван Иванов" autofocus>

Уровень поддержки браузерами атрибута autofocus примерно такой же, как и атрибута placeholder, и означает, что практически все браузеры поддерживают его, за исключением Internet Explorer. Но опять же, эта проблема легко решается. Проверить поддержку атрибута autofocus конкретным браузером можно с помощью инструмента Modernizr (который мы обсуждали в статье «Поддержка браузерами HTML5») и, если необходимо, запускать собственный код для автоматического фокуса.

Создание контактной формы | Gatsby

В этом руководстве рассказывается, как создать контактную форму на сайте Gatsby, а также приводится обзор некоторых стратегий обработки отправленных данных формы.

Gatsby построен на базе React. Таким образом, все, что возможно с формой React, возможно в Gatsby. Дополнительные сведения о том, как добавлять формы на сайт Gatsby, можно найти в разделе «Добавление форм».

Создание формы со специальными возможностями

Неправильные формы являются обычным препятствием для доступа к веб-сайту и могут быть особенно проблематичными, если вы используете клавиатуру и программу чтения с экрана для навигации в Интернете. Формы должны быть четко и интуитивно организованы в группы связанной информации, а каждое поле формы должно быть обозначено соответствующей меткой.

Дополнительную информацию о создании специальных форм можно найти в статье WebAIM на эту тему.

Отправка данных формы

Когда вы отправляете форму, соответствующие данные обычно отправляются на сервер для какой-либо обработки. Более подробную информацию об отправке данных формы можно найти на MDN.

Каждый описанный ниже метод начинается со следующей контактной формы:

Варианты отправки форм в Gatsby

Getform

Getform — это серверная платформа форм, которая предлагает бесплатный план для обработки отправки форм на статических сайтах. Начните с создания формы на своем сайте Gatsby, с которой вы сможете получать материалы. При создании формы направьте метод HTTP POST на Getform, поместив имя атрибуты для полей, которые вы хотите сделать видимыми. (имя, электронная почта, сообщение и т. д.)

После внесения изменений в код формы вы можете перейти на страницу контактов на своем сайте и начать отправку данных в форму. Затем отправленные материалы будут видны на панели инструментов Getform. Вы можете добавить несколько адресов электронной почты, чтобы получать уведомления по электронной почте для созданных форм, а также манипулировать данными, которые вы видите в Getform, с помощью предлагаемых параметров Zapier и Webhooks.

Дополнительную информацию о процессе регистрации и настройке формы можно найти на веб-сайте Getform, а примеры кода (AJAX, reCAPTCHA и т. д.) — на их CodePen.

Netlify

Если вы размещаете свой сайт на Netlify, вы получаете доступ к их превосходной функции обработки форм.

Настройка включает только добавление нескольких атрибутов формы:

Теперь все отправленные формы будут отображаться на вкладке «Формы» панели инструментов вашего сайта. Добавляя атрибут формы netlify-honeypot="bot-field" и соответствующий скрытый ввод, Netlify будет знать, что нужно незаметно отклонять любые спам-сообщения, которые вы можете получить.

Дополнительную информацию о Netlify Forms можно найти на их веб-сайте.

Formspree

Formspree предлагает обширный бесплатный сервис для обработки отправки форм на статических сайтах. Это делает его отличным инструментом для отправки форм непосредственно на адрес электронной почты по вашему выбору с очень небольшой настройкой.

Чтобы начать использовать функции Formspree, вы должны добавить действие формы, направляющее метод HTTP POST в API Formspree (заменив выбранный вами адрес электронной почты), а также изменить атрибут name ввода электронной почты на name="_replyto " .

После внесения изменений вы можете отправить свою собственную форму в первый раз и зарегистрироваться, используя электронную почту, которую Formspree отправит вам, и все последующие отправки форм будут отправлены на ваш адрес электронной почты. Вы можете найти больше информации о процессе регистрации или настройке на их веб-сайте.

Все формы, настроенные таким образом, по умолчанию поставляются с reCAPTCHA, но вы также можете включить фильтрацию спама Honeypot, добавив скрытый элемент ввода с полем name="_gotcha" .

Поскольку ввод скрыт, Formspree будет знать, что только бот мог сделать отправку, и она будет молча проигнорирована!

Запустите свой собственный сервер

Если для обработки ваших данных формы требуется значительный объем бизнес-логики, создание собственной службы может иметь наибольший смысл. Самым популярным решением для этого является написание HTTP-сервера — это можно сделать на многих языках, включая PHP, Ruby, GoLang или, в нашем случае, Node.js с Express.

Первоначальная реализация сервера, использующего Express, Body-parser и nodemailer, может выглядеть так:

Эта первоначальная реализация прослушивает запросы POST на /contact и отправляет вам электронное письмо с отправленными данными формы. Вы можете развернуть этот сервер с такими службами, как Vercel.

После развертывания запишите URL-адрес развертывания (например, my-project-abcd123.vercel.app ) и используйте его в качестве действия формы:

Теперь все последующие формы будут отправляться на ваш адрес электронной почты. !

Подробное руководство по запуску собственного почтового сервера вы можете найти в замечательном руководстве от DataFire.

Другие ресурсы

Если у вас возникли проблемы или вы хотите узнать больше о реализации собственной контактной формы в Gatsby, ознакомьтесь с этим руководством Скотта Толински:

Начать сборку сегодня на

Gatsby Cloud!

Редактировать эту страницу на GitHub

Может ли JavaScript отправить форму по электронной почте?

  • Дом
  • Форма Javascript
электронная почта для начинающихФорма электронной почты на Javascriptmailto

НЕТ! JavaScript не может отправить форму по электронной почте! но есть альтернативы для отправки данных формы на адрес электронной почты.

JavaScript не предоставляет прямого метода для отправки данных, представленных в форме, на адрес электронной почты.

Основной проблемой отсутствия функции «Форма электронной почты JavaScript» является безопасность. Предположим, в JavaScript есть функция для отправки электронной почты. Некоторые вредоносные кодеры могут написать скрипт для отправки электронной почты на какой-либо адрес сразу после посещения их страницы. Это раскроет ваш адрес электронной почты какой-либо третьей стороне без вашего ведома. Они начнут заполнять ваш почтовый ящик большим количеством спам-сообщений! Однако существуют альтернативы, как описано ниже.

Использование «mailto:»

Вы можете использовать «mailto:[email protected]» в поле действия формы. Когда пользователь нажимает кнопку отправки формы, браузер сначала показывает окно с предупреждением о том, что адрес электронной почты пользователя будет раскрыт получателю.

Если пользователь решит продолжить, данные формы будут отправлены на адрес, указанный в теге mailto:. Браузер откроет почтовый клиент по умолчанию для отправки данных по электронной почте.

Код образца

 
com" method="post" enctype="text/plain" > Имя: Электронная почта:

См. приведенный выше пример кода в работе: Пример почтовой формы JavaScript 1

Обратите внимание, что этот метод вообще не требует JavaScript.

Недостатки метода mailto:

Невозможно управлять форматированием данных формы. Данные, представленные в форме, отправляются браузером. Вы не можете контролировать расположение данных.

Браузер показывает окно предупреждения перед отправкой данных. Это может помешать посетителю отправить форму.

Правильный способ отправки отправленных форм по электронной почте — получить отправленные формы в сценарии на стороне сервера, а затем отправить электронное письмо. Язык сценариев на стороне сервера (например, PHP Perl, ASP) имеет больше функций и возможностей для отправки электронной почты.

Узнать больше:

  • Отправка данных формы HTML на адрес электронной почты

  • Как сделать веб-форму

  • Простая форма электронной почты

  • Руководство по контактной форме PHP

  • Руководство по отправке формы Javascript

См.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *