Как работать с формами
Перейти к содержимому

Как работать с формами

  • автор:

Работа с формами

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

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

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

Все файлы в Windows Forms

Несмотря на то, что мы видим только форму, но стартовой точкой входа в графическое приложение является класс Program, расположенный в файле Program.cs:

using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; namespace HelloApp < static class Program < [STAThread] static void Main() < Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); >> >

Сначала программой запускается данный класс, затем с помощью выражения Application.Run(new Form1()) он запускает форму Form1. Если вдруг мы захотим изменить стартовую форму в приложении на какую-нибудь другую, то нам надо изменить в этом выражении Form1 на соответствующий класс формы.

Сама форма сложна по содержанию. Она делится на ряд компонентов. Так, в структуре проекта есть файл Form1.Designer.cs, который выглядит примерно так:

namespace HelloApp < partial class Form1 < /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) < if (disposing && (components != null)) < components.Dispose(); >base.Dispose(disposing); > #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() < this.SuspendLayout(); // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(284, 261); this.Name = "Form1"; this.Text = "Привет мир!"; this.ResumeLayout(false); >#endregion > >

Здесь объявляется частичный класс формы Form1, которая имеет два метода: Dispose() , который выполняет роль деструктора объекта, и InitializeComponent() , который устанавливает начальные значения свойств формы.

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

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

Еще один файл — Form1.resx — хранит ресурсы формы. Как правило, ресурсы используются для создания однообразных форм сразу для нескольких языковых культур.

И более важный файл — Form1.cs, который в структуре проекта называется просто Form1, содержит код или программную логику формы:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace HelloApp < public partial class Form1 : Form < public Form1() < InitializeComponent(); >> >

По умолчанию здесь есть только конструктор формы, в котором просто вызывается метод InitializeComponent() , объявленный в файле дизайнера Form1.Designer.cs. Именно с этим файлом мы и будем больше работать.

React. Работа с формами

Работа элементов HTML-форм в React немного отличается от работы других DOM-элементов, потому что элементы форм по своей природе обладают некоторым внутренним состоянием. К примеру, данная форма в нативном HTML принимает только имя:

form> label> Name: input type="text" name="name" /> /label> input type="submit" value="Submit" /> /form>

Эта форма имеет поведение HTML-формы по умолчанию: просмотр новой страницы, когда пользователь посылает форму. Если вам необходимо это поведение в React, оно работает как обычно. Но в большинстве случаев удобно иметь JavaScript-функцию, которая обрабатывает отправку формы и имеет доступ к данным, которые пользователь ввел в форму. Стандартным способом достижения этой цели является использование подхода «контролируемые компоненты».

Контролируемые компоненты

В HTML-элементы форм, такие как , и как правило хранят свое собственное состояние и обновляют его на основании пользовательского ввода. В React модифицируемое состояние как правило является собственностью компонентов и обновляется только с помощью setState(). Мы можем скомбинировать эти обе особенности, делая состояние React “единственным источником достоверной информации (истины)”. В свою очередь React-компонент, который отрисовывает форму, также контролирует, что происходит на этой форме в ответ на последующий ввод пользователя. Элемент ввода формы (например, input), значение которого контролируется React, в этом случае называется «контролируемый компонент». В большинстве случаев рекомендуется использовать контролируемые компоненты для реализации форм. В контролируемом компоненте данные формы обрабатываются компонентом React.

Основы работы с формами

Пусть у нас в this.state.value хранится текст ‘hello’:

class App extends React.Component  constructor(props)  super(props); this.state =  value: 'hello' >; > >

Теперь в методе render сделаем инпут, и таже же сделаем так, чтобы в value инпута записалось значение из this.state.value:

class App extends React.Component  constructor(props)  super(props); this.state =  value: 'hello' >; > render()  return div> input value=this.state.value> /> /div>; > >

Запустите этот код — на экране вы увидите инпут с текстом ‘hello’. Однако, вас ждет сюрприз: вы не сможете поменять текст нашего инпута. Почему так? Потому что мы четко сказали, что в value инпута должно быть значение из this.state.value. Это значение не меняется — и значит value инпута тоже не будет меняться, даже если вы вручную что-то попытаетесь туда написать. Понятно, что такое поведение не очень удобно и нам нужно что-то с этим сделать. Что именно: нужно организовать двухстороннее связывание

  • this.state.value и value инпута должны зависеть друг от друга: при изменении одного должен меняться и другой. Первый шаг для этого следующий: нужно к нашему инпуту добавить событие onChange и привязать к нему какой-нибудь метод, назовем его, к примеру, handleChange.
class App extends React.Component  constructor()  super(); this.state =  value: 'hello' >; > //Срабатывает при любом изменении инпута: handleChange = () =>  //тут какой-то код > render()  return div> input value=this.state.value> onChange=this.handleChange> /> /div>; > >

Как работает событие onChange? — оно срабатывает при попытке любого изменения инпута. Например, если мы пытаемся ввести в него какой-то текст, то onChange будет срабатывать при каждом вводе символа. И, даже если текст инпута не будет меняться из-за привязанного this.state.value, событие onChange будет срабатывать и каждый раз вызывать метод handleChange. Чтобы содержимое инпута могло изменяться, для этого в методе handleChange нужно в свойство this.state.value записывать содержимое атрибута value нашего инпута.

Работа с textarea

Работа с текстареа осуществляется очень похожим на работу с инпутом образом — также добавляется атрибут value и событие onChange. Следующий код — выведет на экран textarea, в который можно будет вводить текст. Все изменения будут отображаться в абзаце над нашим textarea:

class App extends React.Component  constructor(props)  super(props); this.state =  value: 'hello' >; > //Записываем value текстареа в this.state.value: handleChange = (event) =>  this.setState( value: event.target.value >); > render()  return div> p>текст: this.state.value>/p> textarea value=this.state.value> onChange=this.handleChange> /> /div>; > >

Обратите внимание: React подход отличается подхода на чистом JavaScript. На чистом JS у текстареа нет атрибута value, кроме того, в чистом JS текстареа должен иметь закрывающий тег: , но в реакте мы пишем так: — подобно работе с инпутом.

Чекбоксы

Работа с чекбоксами также осуществляется по схожему принципу, только вместо атрибута value мы указываем атрибут checked. Если в этот атрибут передать true — то чекбокс будет отмечен, а если false — не будет отмечен:

return div> input type="checkbox" checked=тут должно быть true или false> /> /div>;

Конечно же, обычно в checked передается стейт, который может принимать только два значения: или true, или false. Так же, как и при работе с инпутами, если жестко задать значение атрибута checked — состояние чекбокса нельзя будет поменять. Для решения этой проблемы поступим так: будем по изменению чекбокса менять this.state.checked на противоположное ему значение, то есть на !this.state.checked.

class App extends React.Component  constructor(props)  super(props); this.state =  checked: true >; > //Меняем this.state.checked на противоположный: handleCheckboxChange = (event) =>  this.setState( checked: !this.state.checked >); > render()  return div> input type="checkbox" checked=this.state.checked> onChange=this.handleCheckboxChange> /> /div>; > >

Селекты

Давайте теперь займемся выпадающими списками select. Работа с ними также практически не отличается от работы с инпутами и чекбоксами.

class App extends React.Component  constructor(props)  super(props); this.state =  value: 'javascript' >; > //Изменяем this.state.value при изменении селекта: handleSelectChange = (event) =>  this.setState( value: event.target.value >); > render()  return div> p>Ваш выбор: this.state.value>/p> select value=this.state.value> onChange=this.handleSelectChange> > option>html/option> option>css/option> option>javascript/option> /select> /div>; > >

Изначально выбран будет пункт списка со значением ‘javascript’ и этот выбор будет отражаться в нашем абзаце. Но если выбор поменять — в абзаце он тоже поменяется. Давайте теперь тегам option дадим атрибут value, как это обычно и делается:

select> option value="0">Язык HTML/option> option value="1">Язык CSS/option> option value="2">Язык JavaScript/option> /select>

На самом деле без атрибута value, как это было сделано выше — плохо. Почему плохо: ведь текст option может меняться и это повлияет на работу нашего скрипта. К примеру, вместо текста ‘javascript’ мы сделаем текст ‘Язык JavaScript’ и теперь строчка this.state = просто не будет работать. А вот если мы привяжемся к value и напишем this.state =

  • все будет работать независимо от того, что написано в самом тексте тега option.
class App extends React.Component  constructor(props)  super(props); this.state = value: 0>; > //Изменяем this.state.value при изменении селекта: handleSelectChange = (event) =>  this.setState(value: event.target.value>); > render()  return div> p>Ваш выбор: this.state.value>/p> select value=this.state.value> onChange=this.handleSelectChange> > option value="0">Язык HTML/option> option value="1">Язык CSS/option> option value="2">Язык JavaScript/option> /select> /div>; > >

Итак, если вы запустите этот код, то увидите проблему — строка

Ваш выбор: будет выводить value нашего option, а никак не значение. Для того, чтобы поправить эту проблему, вначале сделаем следующее: не будем создавать теги option вручную, а сделаем массив this.state.langs и из этого массива и сформируем наш селект, у нас по-прежнему есть строка this.state.value, которая выводит value option, а не его значение:

p>Ваш выбор: this.state.value>/p>

Давайте поправим ее так, чтобы она подтягивала значение из массива this.state.langs по его ключу this.state.value:

p>Ваш выбор: this.state.langs[this.state.value]>/p>

Радиокнопки

Работа с radio несколько отличается, к примеру, от тех же чекбоксов. Проблема в том, что у нескольких радио будет один и тот же стейт, но разные value. Поэтому работа происходит следующем образом: в атрибут value записывают значение радио, а в атрибут checked — специальное условие, которое проверяет, равен ли this.state.option определенному значению. Если равен — радиокнопка станет отмеченной, а если не равен — будет не отмеченной. Пример: пусть this.state.option — это стейт, в котором будет хранится значение радио. Сделаем 2 радиокнопки и дадим одной value=“option1”, а второй — value=“option2”. Тогда для проверки того, будет ли первая радиокнопка отмечена, ей в атрибут checked запишем следующее: checked=. Получится, что если в this.state.option лежит option1 первая радиокнопка будет отмеченной, а если не лежит — то не будет. Аналогичную строку запишем и для второй радиокнопки — checked=, только здесь мы сравниванием this.state.option уже с option2. Для каждой радио также напишем атрибут onChange и прикрепим к нему метод handleRadioChange. Ну, здесь все как обычно — так же, как для инпутов и чекбоксов. Давайте соберем все вместе и запустим:

class App extends React.Component  constructor(props)  super(props); this.state = option: 'option1'>; > //Изменяет this.state.option при изменении радио: handleRadioChange = (event) =>  this.setState(option: event.target.value>); > render()  return div> p>Ваш выбор: this.state.option>/p> input name="lang" type="radio" value="option1" checked=this.state.option == 'option1'> onChange=this.handleRadioChange> /> input name="lang" type="radio" value="option2" checked=this.state.option == 'option2'> onChange=this.handleRadioChange> /> /div>; > >

Значение по умолчанию

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

class App extends React.Component  constructor(props)  super(props); this.state = value: 'hello'>; > render()  return( div> input defaultValue=this.state.value> /> /div> ); > >

Запустите этот код — и вы увидите на экране инпут со значением ‘hello’. Но это значение можно будет сменить, при этом this.state.value не поменяется — двухсторонней связи нет.

Для чекбоксов существует аналогичный атрибут defaultChecked, с помощью которого можно задать начальное состояние (отмечен или нет):

class App extends React.Component  constructor(props)  super(props); this.state = checked: true>; > render()  return div> input type="checkbox" defaultChecked=this.state.checked> /> /div>; > >

Written by Vadim Goloviychuk

Формы и javascript. FORM

Сейчас мы поговорим о различных приемах работы сценариев JavaScript с HTML-формами.

Если в HTML-документе определена форма, то она доступна сценарию JavaScript как объект, входящий в объект document с именем, заданным атрибутом NAME тега FORM .

Свойства форм

Форма имеет два набора свойств, состав одного из которых фиксированный, а состав другого зависит от того, какие элементы определены в форме.

Свойства первого набора

  • action. Значение атрибута ACTION тега FORM .
  • encoding. Значение атрибута ENCTYPE тега FORM .
  • method. Значение атрибута METHOD тега FORM .
  • target. Значение атрибута TARGET тега FORM .
  • elements. Массив всех элементов формы.
  • length. Размер массива elements.

Элементы форм

Кнопки (BUTTON, RESET, SUBMIT)

Свойства
  • name. Имя объекта.
  • value. Надпись на кнопке.
Метод
  • click( ). Вызов этого метода тождественен щелчку мышкой по кнопке.
Пример
      

Нажатие кнопки

Нажатие кнопки

Флажок (CHECKBOX)

Свойства
  • name. Имя объекта.
  • value. Надпись на кнопке.
  • checked. Состояние флажка: true — флажок установлен, false — флажок не установлен.
  • defaultChecked. Отражает наличие атрибута CHECKED : true — есть, false — нет.
Метод
  • click( ). Вызов этого метода меняет состояние флажка.
Пример
    

Метод click флажка

Флажок Состояние флажка можно изменить и этой кнопкой

Метод click флажка

Переключатель (RADIO)

Свойства
  • name. Имя объекта.
  • value. Надпись на кнопке.
  • length. Количество переключателей в группе.
  • checked. Состояние переключателя: true — переключатель включен, false — выключен.
  • defaultChecked. Отражает наличие атрибута CHECKED : true — есть, false — нет.
Метод
  • click( ). Вызов этого метода включает переключатель.
Пример
     

Метод click группы переключателей

Мужской Женский Состояние переключателей можно изменить и этой кнопкой

Метод click группы переключателей

Список (SELECT)

Свойства
  • name. Имя объекта.
  • selectedIndex. Номер выбранного элемента или первого среди выбранных (если указан атрибут MULTIPLE ).
  • length. Количество элементов (строк) в списке.
  • options. Массив элементов списка, заданных тегами OPTION .
  • value. Значение атрибута VALUE .
  • text. Текст, указанный после тега OPTION .
  • index. Индекс элемента списка.
  • selected. Присвоив этому свойству значение true , можно выбрать данный элемент.
  • defaultSelected. Отражает наличие атрибута SELECTED : true — есть, false — нет.
Методы
  • focus( ). Передает списку фокус ввода.
  • blur( ). Отбирает у списка фокус ввода.
Пример
     

Работа с готовым списком

Работа с готовым списком

Кроме работы с готовыми списками JavaScript может заполнять список динамически. Для записи нового элемента списка используется конструктор Option c четырьмя параметрами, первый из которых задает текст, отображаемый в списке, второй — значение элемента списка, соответствующее значению атрибута VALUE , третий соответствует свойству defaultSelected , четвертый — свойству selected .

Пример
    

Динамическое заполнение списка

Динамическое заполнение списка

Поле ввода (TEXT)

Свойства
  • name. Имя объекта.
  • defaultValue. Начальное содержимое поля.
  • value. Текущее содержимое поля.
Методы
  • focus( ). Передает полю фокус ввода.
  • blur( ). Отбирает у поля фокус ввода.
  • select( ). Выделяет содержимое поля.
Пример
      

Заполните анкету

Фамилия: Имя: Возраст: Телефон:

Заполните анкету

Обратите внимание на то, что символы фамилии и имени при потере фокуса соответствующими полями преобразуются в прописные. Для этого используется метод toUpperCase , определенный во встроенном классе строк.

Текстовая область (TEXTAREA)

Свойства
  • name. Имя объекта.
  • defaultValue. Начальное содержимое области.
  • value. Текущее содержимое области.
Методы
  • focus( ). Передает области фокус ввода.
  • blur( ). Отбирает у области фокус ввода.
  • select( ). Выделяет содержимое области.
Пример
      

Отправьте телеграмму

Отправьте телеграмму

Для установки курсора в определенное место textarea-области используйте следующую кросбраузерную функцию: