Html onsubmit form: Событие onsubmit | htmlbook.ru

НОУ ИНТУИТ | Лекция | HTML-формы

Аннотация: В данной лекции подробным образом разбираются элементы разметки, входящие в группу HTML-FORM. Рассматриваются их атрибуты, совместимость атрибутов и форматы записи данных при формировании запросов к HTTP-серверу.

Ключевые слова: form, контейнер, тег, атрибут, Action, методы передачи данных, разбиение, HTTP, схема URL, CGI, QUERY_STRING, submit, input, mosaic, textarea, SELECT

Элемент разметки FORM и его компоненты

Контейнер (элемент разметки) FORM позволяет определить в рамках HTML-документа форму ввода. В рамках этого контейнера размещаются все поля ввода, куда пользователь может поместить свою информацию. Если контейнер формы открыт, т.е. в документе указан тег начала контейнера <FORM …>, то обязательно нужно указать и тег конца контейнера </FORM>.

В общем случае контейнер имеет следующий вид:

<FORM 
NAME=. ..
ACTION=url
METHOD=POST|GET|PUT|...
enctype=application/x-www-form-urlencoded|
        multipart/form-data
[target=window_name]
>
...
</FORM>

Атрибут NAME используется для именования формы. Это делается главным образом в JavaScript-программах. Атрибут ACTION задает URL, по которому отправляются данные из формы. Атрибут METHOD определяет метод передачи данных (фактически, речь идет о формировании сообщения, передаваемого по сети). Атрибут ENCTYPE определяет тип кодирования данных в теле сообщения и разбиение сообщения на части. Необязательный атрибут TARGET позволяет адресовать окно, в котором будет отображаться результат обработки данных из формы.

В рамках обзора применения контейнера FORM мы рассмотрим:

  • передачу данных по электронной почте;
  • передачу данных скрипту через атрибут ACTION ;
  • intuit.ru/2010/edi»>передачу данных через Server Side Include.

Инициировать обмен можно при помощи JavaScript-кода, но рассматривать данный способ программирования обмена данными мы здесь не будем.

FORM (mailto)

Контейнер FORM позволяет определить в рамках HTML-документа форму ввода. В рамках этого контейнера размещаются все поля ввода, в которые пользователь может поместить информацию. Часто автор страниц Web-сайта по тем или иным причинам не имеет возможности программировать на стороне сервера. Однако это не означает, что он не может применять формы. Формы можно применять для отправки почты. Однако, как и в любом деле, здесь есть свои особенности, например:

<FORM ACTION=mailto:[email protected]>
<INPUT NAME=n1 VALUE="Поле1">
<INPUT TYPE=SUBMIT VALUE="Отправить">
</FORM>

В данном примере ( cgimail1. htm ) мы пытаемся отправить значение поля формы n1 по электронной почте абоненту [email protected]. После заполнения поля и выбора кнопки «Отправить», браузер откроет окно программы почтового клиента, что не входило в наши планы. При этом само значение поля куда-то исчезнет.

Почему открывается новое окно? Несмотря на полный произвол, который царит в Web, и жесточайшую конкуренцию между Netscape и Microsoft, логика, заложенная в архитектуру World Wide Web Бернерсом Ли, обеими компаниями соблюдается. Дело в том, что, согласно спецификации RFC 822 (формат текстового сообщения Internet), на которую опираются протоколы HTTP и SMTP (Simple Mail Transfer Protocol, простой протокол электронной почты), сообщение может состоять из двух частей: заголовка и тела. В том виде, в каком мы используем контейнер FORM , метод доступа к ресурсу не указан и, следовательно, по умолчанию выбирается GET. У нас нет тела сообщения, а есть только заголовок.

intuit.ru/2010/edi»>Кроме того, в примере мы применяем схему URL mailto. Она соответствует спецификации протокола SMTP (обмен почтовыми сообщениями в Internet). В этой схеме, в отличие от схемы HTTP, расширенный путь после доменного имени стандартом не предусмотрен.

Итак, для того, чтобы получить тело сообщения, необходимо указать метод POST ( cgimail2.htm ). В этом случае сообщение должно уйти абоненту без открытия окна почтового клиента:

<FORM METHOD=post 
      ACTION=mailto:[email protected]>
<INPUT NAME=n1 VALUE="Поле1">
<INPUT TYPE=SUBMIT VALUE="Отправить">
</FORM>

Любопытно, что в данном случае мы использовали протокол, отличный от HTTP — SMTP. В нем нет понятия метода доступа вообще. Тем не менее логика разбиения текстовых сообщений для всех протоколов одна и та же, как, собственно, и предполагалось при создании Web-технологии — унификация доступа к ресурсам.

На этом примере хорошо видны отличия URI от URL. В данном случае были возможны различные механизмы обработки данных в запросе на ресурс, который задается URI. Но конкретная реализация преобразования данных в запрос в рамках Web — это и есть URL, т.е. URI в рамках World Wide Web.

Расширим наш пример, добавив в него отправку абоненту внешнего файла по электронной почте. Такая задача встречается довольно часто. Например, поддержка архива электронных публикаций. Здесь нет необходимости в немедленном опубликовании материалов. Все статьи должны пройти экспертизу, которая требует определенного времени. Для этого модифицируем наш пример, добавив в него поле типа FILE:

<FORM METHOD=post 
      ACTION=mailto:[email protected]>
<INPUT NAME=n1 VALUE="Поле1">
<INPUT NAME=file TYPE=file>
<INPUT TYPE=SUBMIT VALUE="Отправить">
</FORM>

ru/2010/edi»>Почему в данном случае нельзя использовать метод GET, объяснялось выше. Метод POST должен обеспечить нам размещение всего файла в теле сообщения.

Однако все это верно, пока мы работаем с текстовыми файлами и находимся в рамках RFC822. А если нам нужно передать файл с длинными строками (Postscript) или просто двоичный файл? В таком случае необходимо обратиться к формату MIME. Это можно сделать при помощи еще одного атрибута контейнера FORM — ENCTYPE:

<FORM
ENCTYPE=multipart/form-data
METHOD=post
ACTION=mailto:[email protected]>
<INPUT NAME=n1 VALUE="Поле1">
<INPUT NAME=file TYPE=file>
<INPUT TYPE=BUTTON VALUE="Отправить">
</FORM>

В данном случае по почте отправляется сообщение не в стандарте RFC822, а в стандарте MIME. Тело сообщения будет состоять из нескольких частей, а файл будет преобразован в ASCII-символы в соответствии со спецификацией BASE-64. Стандартный почтовый клиент воспринимает такой файл как присоединенный и позволяет его либо просмотреть, либо сохранить на диске.

FORM (HTTP)

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

Раз запрос от клиента принимает сервер, следовательно, и инициировать изложенные выше действия должен именно он.

Механизм инициирования такой прикладной программы определен в спецификации Common Gateway Interface. Там же задан и порядок обмена данными между HTTP -сервером и программой, которая в спецификации CGI именуется скриптом.

Метод GET

Основная задача формы — это предоставление шаблона ввода данных, которые будут переданы скрипту. Сам скрипт при этом указывается через URL, который задается в атрибуте ACTION :

<FORM ACTION=script.cgi>
<INPUT NAME=n1 VALUE="Поле1">
<INPUT NAME=n2 VALUE="Поле2">
<INPUT TYPE=SUBMIT VALUE="Отправить">
</FORM>

В данном примере скрипт просто распечатывает пару «имя поля формы — значение поля формы» в виде HTML-таблицы ( formcgi1.htm ). Правда, если присмотреться внимательно к происходящему на экране, можно обнаружить любопытную метаморфозу с URL скрипта при выборе кнопки «Отправить». В поле location окна браузера к скрипту после символа » ?» приписываются пары «поле-значение», разделенные символом » & «.

Данный запрос из формы определяют как запрос типа URLENCODED, переданный по методу GET. При передаче значений по методу GET формируется только заголовок HTTP -сообщения и не формируется его тело. Поэтому все содержание полей формы помещается в URL и таким образом передается скрипту. Из текста скрипта ( formcgi2.htm ) видно, что данные извлекаются из переменной окружения QUERY_STRING, в которую сервер помещает запрос.

Запросы, которые передаются в методе GET, можно условно разделить на два типа: ISINDEX и FORM-URLENCODED. FORM-URLENCODED мы только что рассмотрели, а ISINDEX был описан в разделах «Заголовок HTML-документа» и «Спецификация Common Gateway Interface», поэтому не будем повторяться.

Метод POST

Очевидно, что в строку URL нельзя втиснуть бесконечное число символов. И браузер, и среда, в которой функционирует сервер, имеют ограничения либо, как в случае браузера, по длине поля location, либо по длине области переменных окружения. Правда, последнее для современных систем не очень актуально. Например, операционная система IRIX 6.2 позволяет размещать в области переменных окружения данные объемом до 4 Mбайт. Тем не менее, для передачи относительно больших объемов предпочтительнее использовать метод доступа POST:

<FORM METHOD=post ACTION=script.cgi>
<INPUT NAME=n1 VALUE="Поле1">
<INPUT NAME=n2 VALUE="Поле2">
<INPUT TYPE=BUTTON VALUE="Отправить">
</FORM>

В нашем примере в контейнере FORM появился атрибут METHOD, который принял значение POST. Результат работы скрипта не изменился, но сам скрипт претерпел существенные изменения. Теперь запрос принимается со стандартного ввода, а не из переменной окружения QUERY_STRING.

При методе POST данные передаются как тело HTTP -сообщения, и скрипт читает их со стандартного ввода. При этом есть один существенный нюанс, который ограничивает круг средств разработки скриптов для приема данных по POST. Он заключается в том, что сервер не закрывает канал передачи данных скрипту после передачи последнего символа запроса. В переменной CONTENT_LENGTH сервер сообщает, сколько данных со стандартного ввода нужно считать. Таким образом, язык программирования сценариев или универсальный язык программирования должны уметь читать определенное количество символов из стандартного ввода. Например, многие разновидности командных языков UNIX (Bourn-shell, Kernel-shell и т.п.) могут читать только строками и ждут закрытия входного потока.

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

Кодирование

Существует два типа кодирования содержания (тела) HTTP -сообщения, которые можно определить в форме:

  • intuit.ru/2010/edi»>application/x-www-form-urlencoded
  • multipart/form-data

Все, что рассматривалось в данном разделе до сих пор, относилось к первому типу кодирования тела HTTP -сообщения. Первый тип кодирования выбирается по умолчанию и является основным способом. Единственное, что пока не было рассмотрено, так это то, что, собственно, представляет собой этот самый URLENCODED.

В URL документа можно использовать только символы набора Latin1. Это первая половина таблицы ASCII за вычетом первых 20 символов. Все остальные символы заменяются своими шестнадцатеричными эквивалентами. Кроме того, такие символы, как » + » или » & «, играют роль разделителей или коннекторов. Если они встречаются в значении поля, то тоже заменяются на шестнадцатеричный эквивалент. Наиболее характерно это для работы с русским алфавитом. Поэтому скрипт, который принимает запросы, должен уметь эти символы декодировать.

Второй тип применяется для передачи двоичной информации в теле HTTP -сообщения. Если проводить аналогии с электронной почтой, то multipart/form-data обеспечивает присоединение файла данных (attachment) к HTTP -запросу. Наиболее типичным примером является передача файла с машины пользователя на сервер:

<FORM ACTION=script.cgi METHOD=post 
      ENCTYPE=multipart/form-data>
<INPUT NAME=n1 VALUE="Поле1">
<INPUT NAME=n2 TYPE=file>
<INPUT TYPE=SUBMIT VALUE="Отправить">
</FORM>

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

FORM (SSI)

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

Во-первых, атрибут ACTION можно не указывать в том случае, если данные, введенные в форму, обрабатываются JavaScript-программой. В этом случае достаточно дать форме имя, чтобы к ее элементам (контейнерам) можно было обращаться. Передачу данных можно реализовать через метод submit , который будет выполняться при нажатии на гипертекстовую ссылку, например, formssi1.htm. Более подробно данный материал описан в главе «Программирование на JavaScript».

Во-вторых, принять данные можно через скрипт, который встроен в документ как Server Side Include. Этот способ мы рассмотрим более подробно.

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

<FORM>
<INPUT NAME=n1 VALUE="Поле1">
<INPUT NAME=n2 VALUE="Поле2">
<INPUT TYPE=SUBMIT VALUE="Отправить">
</FORM>

то после перезагрузки документа мы получим этот же документ, только в URL после символа » ?» будет добавлено содержание формы ( formssi2.htm ).

Если теперь несколько видоизменить документ — вставить в него Server Side Include — получим:

<FORM>
<INPUT NAME=n1 VALUE="Поле1">
<INPUT NAME=n2 VALUE="Поле2">
<INPUT TYPE=SUBMIT VALUE="Отправить">
<HR>
<!--#exec cgi=./cgi.cgi -->
</FORM>

Сам скрипт принимает запрос из QUERY_STRING и распечатывает его в виде HTML-таблицы ( formssi3.htm ). При этом результат распечатывается вслед за формой после горизонтального отчеркивания.

intuit.ru/2010/edi»>Точно так же можно обработать данные и методом POST, только для этого необходимо указать его в атрибуте METHOD контейнера FORM .

Как ввести форму React для обработчика onSubmit

Вот форма в JSX :

 

function UsernameForm({onSubmitUsername}) {

function handleSubmit(event) {

2 onSubmit()

5 000002 event.prevent .currentTarget.elements.usernameInput.value)

}

return (

)

}

Пусть

функция handleSubmit . Вот как это делают некоторые люди (копирование этот подход из некоторых сообщений в блогах и «полуофициальных руководств», которые я видел):0005

const form = event.currentTarget

const formElements = form. elements as typeof form.elements & {

usernameInput: {value: string}

}

onSubmitUsername(formElements.usernameInput.value)

5 }

Причина, по которой мы должны иметь как , заключается в том, что TypeScript не совсем достаточно умны, чтобы знать, какие элементы мы отображаем в нашей форме, поэтому мы должны используйте тип приведения, который я не фанат, но вы должны отправить правильно?

Моим первым улучшением этого является изменение usernameInput type:

 

- usernameInput: {value: string}

+ usernameInput: HTMLInputElement

Определенно используйте преимущества типа, которым он является на самом деле, а не просто вишневый выбор значений, которые вам нужны.

Второе улучшение:

 

- function handleSubmit(event: React.SyntheticEvent) {

+ function handleSubmit(event: React.FormEvent) {

Кстати, на момент написания статьи существенной разницы в эти типы, но я предпочитаю быть более ясным и точным с названием тип, так что это то, что мы собираемся пойти с.

Итак, мы здесь:

 

function handleSubmit(event: React.FormEvent) {

event.preventDefault()

const form = event.currentTarget

const formElements = form.elements as typeof form.elements .элементы & {

usernameInput: HTMLInputElement

}

onSubmitUsername(formElements.usernameInput.value)

}

Но даже с этими изменениями я не сторонник этого по трем причинам:

9010’s averbose 9010 отвлекает от основной цели функции
  • Если мне нужно использовать эту форму в другом месте, мне придется либо дублировать код или извлеките тип и приведите его везде, где я использую форму.
  • Мне не нравится видеть как в моем коде, потому что это сигнал, который я говорю компилятор TypeScript для конвейера (будет менее полезным). Поэтому я стараюсь избегать этого когда возможно. И это возможно!
  • Имейте в виду, что мы сообщаем TypeScript, что это такое тип event. currentTarget . Мы сообщаем TypeScript, когда указываем тип для наше событие . Сейчас установлено значение React.FormEvent . Так мы говорим TypeScript, что event.currentTarget — это HTMLFormElement , но затем мы немедленно сообщаем TypeScript, что это не совсем правильно, используя как . Что, если вместо этого мы просто более точно укажем TypeScript, что это такое в начале? Да, давайте так.

     

    interface FormElements extends HTMLFormControlsCollection {

    usernameInput: HTMLInputElement

    }

    interface UsernameFormElement extends HTMLFormElement {

    // теперь мы можем переопределить тип элемента, чтобы он был HTMLFormElement0005

    // нашего собственного дизайна...

    элементы только для чтения: FormElements

    }

    Итак, на самом деле наша форма представляет собой HTMLFormElement с некоторыми известными элементами . Так мы расширяем HTMLFormElement и переопределяем элемента , чтобы иметь элементы, которые мы хочу этого. Тип HTMLFormElement['elements'] представляет собой HTMLFormControlsCollection , поэтому также создайте собственную версию этого интерфейса.

    Теперь мы можем обновить наш тип и избавиться от приведения типов!

    Вот все это в целом:

     

    Import * As React из 'React'

    Формирования интерфейса Extends HtmlformControlScollection {

    usernameInput: htmlinputelement

    }

    eRecfaceInment: htmlinputelement

    }

    Interface uSerMelemelement extendEmentement

    }

    .

    функция UsernameForm({

    onSubmitUsername,

    }: {

    onSubmitUsername: (имя пользователя: строка) => void

    }) {

    function handleSubmit(event: React.FormEvent) {

    event.preventDefault()

    имяпользователя currentTarget.elements.usernameInput. value)

    }

    return (

    5 90 тип="текст" />

    )

    }

    Итак:

  • из информации удалено код handleSubmit , позволяющий нам сосредоточиться на том, что делает функция.
  • Если нам нужно использовать эту форму где-то еще, мы можем дать ей UsernameFormElement введите и получите всю необходимую помощь.
  • Нам не нужно использовать приведение типов, поэтому TypeScript может быть для нас более полезным.
  • Я надеюсь, что это полезно для вас! .

    Предоставляет onSubmit , onChange , listen , submitForm , getFormData , и getInputData функций.

    Эта библиотека будет работать с аналитикой или как отдельный импорт в вашем коде.

    Посмотреть живую демонстрацию.

    Как установить

    Установите @analytics/form-utils из npm.

     npm install @analytics/form-utils 

    API

    Ниже приведен API для @analytics/form-utils . Вы можете импортировать только то, что вам нужно, а остальное будет удалено из вашего пакета.

    onSubmit

    Слушайте отправку форм и делайте что-то с входными данными.

    Это инициирует отправку формы и запускает настраиваемый обратный вызов перед отправкой формы в обычном режиме

     импорт { onSubmit } из '@analytics/form-utils'
    // Добавляем в одиночную форму
    const formOne = document.querySelector('form[id=one]')
    onSubmit(formOne, (событие, данные) => {
      console.log('форма', event.target)
      console.log('данные формы', JSON.stringify(данные, ноль, 2))
    })
    // Добавляем в единую форму с опциями
    onSubmit('форма[id=два]', {
      /* Включите отладку, чтобы отключить отправку и увидеть значения */
      отладка: правда,
      /* Отключить фильтр конфиденциальных значений */
      отключить фильтр: ложь,
      /* Исключить поле по имени или шаблону регулярного выражения атрибута имени */
      исключитьПоля: [
        /частный/,
        'шшш'
      ],
      /* Функция пользовательского фильтра. \d{4}[-]?\d{4}[-]?\d{4}[-]?\d{4}$/)) {
          вернуть ложь
        }
        вернуть истину
      }
    }, (событие, данные) => {
      console.log('форма', event.target)
      console.log('данные формы', JSON.stringify(данные, ноль, 2))
    })
    // Удалить прослушиватель onSubmit
    const cleanUpFunction = onSubmit('form[id=three]', (событие, данные) => {
      console.log('форма', event.target)
      console.log('данные формы', JSON.stringify(данные, ноль, 2))
    })
    cleanUpFunction() // <-- вызов функции для очистки слушателя
    // Слушаем все формы на странице
    onSubmit('все', (событие, данные, метаданные) => {
      console.log('форма', event.target)
      console.log('данные формы', JSON.stringify(данные, ноль, 2))
    }) 

    onChange

    Слушайте изменения формы и делайте что-то с входными данными.

     импорт { onChange } из '@analytics/form-utils'
    // Добавляем в одиночную форму без опций
    const formOne = document.querySelector('form[id=one]')
    onChange(formOne, (событие, данные) => {
      console.log('форма', event. \d{4}[-]?\d{4}[-]?\d{4}[-]?\d{4}$/)) {
          вернуть ложь
        }
        вернуть истину
      }
    }, (событие, данные) => {
      console.log('форма', event.target)
      console.log('изменить данные', JSON.stringify(данные, ноль, 2))
    })
    // Удалить прослушиватель onChange
    const cleanUpFunction = onChange('form[id=three]', (событие, данные) => {
      console.log('форма', event.target)
      console.log('изменить данные', JSON.stringify(данные, ноль, 2))
    })
    cleanUpFunction() // <-- вызов функции для очистки слушателя
    // Слушаем все формы на странице
    onChange('все', (событие, данные) => {
      console.log('форма', event.target)
      console.log('данные формы', JSON.stringify(данные, ноль, 2))
    }) 

    listen

    Listen прикрепит onChange и onSubmit слушателей в формы

     import { listen } from '@analytics/form-utils'
    // Добавляем в одиночную форму без опций
    const formOne = document.querySelector('form[id=one]')
    слушать (formOne, (событие, данные, тип) => {
      console. log('тип прослушивания', тип)
      console.log('форма прослушивания', event.target)
      console.log('прослушивать данные формы', JSON.stringify(данные, ноль, 2))
    })
    // Слушаем все формы с опциями
    слушать({
      /* Включите отладку, чтобы отключить отправку и увидеть значения */
      отладка: правда,
      /* Отключить фильтр конфиденциальных значений */
      отключить фильтр: ложь,
      /* Обработчик пользовательской функциональности для onSubmit */
      onSubmit: (событие, данные) => {
        console.log('отправить форму', event.target)
        console.log('отправить данные', JSON.stringify(данные, ноль, 2))
      },
      onChange: (событие, данные) => {
        console.log('форма изменения', event.target)
        console.log('изменить данные', JSON.stringify(данные, ноль, 2))
      },
      /* // Включить только определенные формы. Это отрицает «все»
      включить формы: [
        'форма[идентификатор=контент-форма]',
        окно.документ.формы[1]
      ],
      */
      /* // Исключаем формы по селекторам или узлу.
      исключитьФормы: [
        'форма [имя = два]',
        окно. \d{4}[-]?\d{4}[-]?\d{4}[-]?\d{4}$/)) {
          вернуть ложь
        }
        вернуть истину
      }
      /**/
    }) 

    submitForm

    Submit form via JS

     import { listen } from '@analytics/form-utils' 

    getFormData

    Get values ​​from form inputs

     import { getFormData } from '@analytics/form -утилиты
    константная форма = document.querySelector('form[id=one]')
    константные данные = getFormData (форма)
    console.log('data', JSON.stringify(data, null, 2)) 

    getInputData

    Получить значение из одной формы ввода

     импорт {getInputData} из '@analytics/form-utils'
    константная форма = document.querySelector('form[id=one]')
    const inputName = 'электронная почта'
    const inputData = getInputData (форма, inputName)
    console.log('inputData', JSON.stringify(inputData, null, 2)) 

    filterData

    Отфильтровать и опустить чувствительные поля

     import {getFormData, getInputData, filterData} from '@analytics/form-utils '
    константная форма = document.

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

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