Главная > AJAX, ExtJS Framework, Open Source > Начало начал или пошаговое создание простой формы на ExtJS

Начало начал или пошаговое создание простой формы на ExtJS

30 ноября 2007

ext_bld_logo1.jpgПриветствую всех наших читателей, и сразу прошу прощения за долгое отсутствие, честно, был сильно занят как в офф-лайне, так и здесь, так что это был вынужденный перерыв, и, поверьте, сам уже заскучал за блогом. А пообщавшись в привате с несколькими людьми, я заметил, что начинающие изучать AJAX на примере ExtJS часто не могут разобраться даже с самой основой - созданием и обработкой обычной формы. Поэтому я решил написать руководство, попутно разобрав внутренности библиотеки. Замечу, что основываться мы будем на версии ExtJS 1.1.1, а про 2.0 поговорим в одном из следующих выпусков.

И так, формы в ExtJS основываются на основном классе BasicForm. Этот класс, с которым напрямую вы не будете контактировать, описывает основное поведение форм, в том числе и реакцию на подтверждение (отправку данных). Это событие в терминах ExtJS имеет название "do actions". Основная же форма будет конструироваться на основе класса Ext.form.Form.

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

  • actioncomplete - событие возникает, когда форма успешно обработана.
  • actionfailed - событие, когда форма не обработана или в процессе возникли ошибки.
  • beforeaction - событие предшествует обработке формы, так что если вам надо встроить свою проверку или другие действия, которые могут повлиять на всю форму - вставьте свой код здесь, а для отмены последующей обработки формы верните false.
  • clientvalidation - формы в ExtJS имеют возможность валидации данных непосредственно на клиенте, а это событие происходит при проверке формы и передаёт флаг результата проверки true если все отлично, и false, если форма заполнена неверно.

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

full_form.png

form_require_fields.pngКстати, заметили красные подчёркивание и значки возле формы? Это как раз валидация формы, а когда она не заполнена, естественно, что все поля не проходят проверку. А значки рядом - это подсказки про поле, там, например, можно написать, как верно заполнять форму, а позже, при проверке, выводить предупреждение о неверности заполнения. При пустой форме там указывается на те поля, которые объявлены как обязательные для заполнения.

Теперь начнём подготовку к созданию формы. Создаём обычную HTML страницу, в которой подключаем необходимые файлы ExtJS, думаю, этот момент не вызовет сложностей, поэтому опускаю его. Сама форма требует одного или нескольких элементов div на странице, которые обеспечат ей место для отображения и сопутствующие элементы. Я использовал часть кода с одного из примеров:

form_html.png

Блоки из трёх вложенных div-тегов с классами x-box-* отвечают за формирование этой самой рамки с заокругленными углами и тенями, в принципе, это вам может и не понадобится. Основной элемент - это внутренний div с идентификатором "register_form", именно он будет указываться как основа для рендеринга формы.

Теперь дело за наполнением. Дело в том, что есть как минимум два варианта создания и наполнения формы отдельными элементами управления. Первый состоит в том, что мы прямо в конструкторе описываем все элементы в виде JSON массива или объявления объектов, именно так сделано в тестовых примерах в документации. Честно говоря, я почему-то считаю, что этот метод не всегда самый лучший, так как сложно потом обращаться напрямую к определённым элементам формы (но можно через метод findField). Либо вручную создавать отдельные объекты полей формы, настраивать их поведение как нужно, а потом добавлять в существующую форму через метод add.

В нашем примере мы пойдём по пути официальной документации и сразу опишем все поля формы.

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

    Ext.QuickTips.init();

    Ext.form.Field.prototype.msgTarget = 'side';

Далее, для удобства, объявляем переменную, которая будет хранить весь объект формы:

    var reg_form;

Теперь мы подошли к самому главному - описанию самой формы. Сначала определяется форма и ее основные данные:

  • url - адрес, куда будут отправлены данные формы. Для примера: http://ваш.серевер/form_script.php
  • timeout - таймаут ожидания ответа от сервера, в секундах, по умолчанию 30 секунд.
  • method - метод, которым отправляются данные на сервер, GET или POST.
  • labelWidth - длина описаний для полей, в пикселях.
  • labelAlign - где по отношению к полю размещается описание.
  • fileUpload - если в форме используется загрузка файлов, то этот флаг следует установить в true.
  • buttonAlign - выравнивание кнопок формы, например кнопок submit/cancel.
  • Если вы используете XML вместо JSON для обмена данными с сервером, необходимо переопределить свойства errorReader (отвечает за получение данных об ошибках заполнения формы от сервера) и reader.
  • baseParams - если вам необходимо передавать какие-то особые параметры вместе с формой, например, идентификатор сессии, то вместо hidden-полей лучше всего использовать это свойство, присваивая ему объект с необходимыми параметрами (или JSON-данные). Для передачи с формой идентификатора сессии можно сделать так: baseParams = {"PHPSESSID":"<?php echo session_id(); ?>"};

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

reg_form = new Ext.form.Form({

        	labelAlign: 'right',

        	labelWidth: 75,

        	url:'register_processed.php?PHPSESSID=<?php echo session_id(); ?>',

        	method: 'POST',

        	fileUpload : false,

        	timeout: 10

    });

Как видите, вместо baseParams можно и напрямую присваивать необходимые переменные в строке url, они все равно будут переданы на сервер. Хотя это и вносит некоторую неразбериху, поэтому в реальных проектах все же выберите себе свой стиль.

Теперь немного о самой архитектуре формы. Она состоит из колонок, в которых содержаться наборы полей, объединённых в элемент fieldset ( да-да, аналог из HTML-а). То есть, сама форма состоит из иерархического набора вложенных элементов. Для нашей формы мы создаём одну колонку и в ней один набор полей. За это отвечает объект Ext.form.Column. У него есть достаточно много свойств, можете разобраться с ним, если будете создавать очень сложные формы, с множеством групп элементов и зависимостями между ними. Для нас сейчас это не так важно, поэтому просто создаём одну колонку размером 400 на 400 пикселей, а для заголовка отводим 100 пикселей:

reg_form.column({width:400, height: 400, labelWidth:100});

Далее нам необходимо создать набор полей формы. Основной для этого является объект Ext.form.FieldSet. Как и в его собрата из HTML, набор полей ограничивается рамкой, и можно задать название формы. Впрочем, при создании есть возможность определить достаточно много свойств, можете просмотреть документацию, нам же пригодится только свойство legend, в котором объявим название формы, а вторым параметром передадим массив наших элементов формы.

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

  • Ext.form.Checkbox
  • Ext.form.ComboBox - достаточно продвинутый элемент, имеющий и автодополнение, и возможность заполнения данными с сервера и множество других "вкусностей".
  • Ext.form.HtmlEditor - простой визуальный редактор. В 1.1 версии возможно только один редактор на странице.
  • Ext.form.NumberField - расширенное обычное поле ввода для работы с цифровыми данными.
  • Ext.form.Radio
  • Ext.form.TextArea
  • Ext.form.TextField

Это основные элементы, с которых мы будем строить нашу форму. Дополнительно нам пригодится еще класс Ext.form.VTypes, который предоставляет возможности валидации типичных данных для полей ввода. Пока по умолчанию доступны следующие типы: alphanum (только строчные и заглавные буквы и цифры, правда не работает с кириллицей), email (для проверки адресов электронной почты) и url для проверки адресов страниц. При необходимости можно реализовать и свою проверку.

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

form_fields_.gif

Наш пример использует только обычные поля ввода, Ext.form.TextField, но работа с остальными не так и отличается, только в случае, к примеру, использования ComboBox с загрузкой данных с сервера. Мы пока будем изучать самую простую форму. В ней мы предусмотрим следующие поля и ограничения для них:

  • Логин - от 4 до 20 символов, латинские буквы и цифры, обязательно должно быть заполнено.
  • Пароль - те же требования, но нельзя отображать символы, их нужно заменить на знаки подстановки.
  • Бета-ключ - обязательное поле, содержащие специальный код для регистрации, строго длина 32 символа.
  • Имя - может содержать от 4 до 100 символов, и может содержать кириллицу, поэтому стандартный валидатор не пройдёт, проверять будем только заполнение и длину, а детальную проверку оставим на серверную сторону.
  • Почтовый адрес - должен содержать только адрес e-mail и не может быть больше 100 символов. Здесь уместно использовать стандартный валидатор.

На рисунке сбоку показан этот участок кода, описывающий эти элементы. Заметьте, что можно устанавливать начальные значение полей через свойство value, а свойство allowBlank указывает на то, может ли поле оставаться пустым, или это будет считаться ошибочным заполнением и такое поле не пройдёт валидацию. Свойство vtype устанавливает необходимый валидатор для поля.

Теперь нам необходимо закрыть колонку, для этого используем код:

reg_form.end();

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

reg_form.applyIfToFields({

        	width:230

    });

Далее можно уже заняться кнопками - ведь какая это форма без кнопок. Нам необходимо две кнопки - подтверждение ввода данных (submit), в качестве которой у нас выступает кнопка "Регистрация пользователя", и кнопка отмены, которая возвращает все поля формы в свои начальные значения.

Для добавления кнопок и связывания с ними обработчиков мы применим метод формы addButton. Вызывая его каждый раз мы будем добавлять кнопки, которые будут выстроены в порядке добавления слева направо.

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

 reg_form.addButton(
        {handler: form_data_eval, text: 'Регистрация пользователя', type:'submit'},
        form_data_eval, reg_form);
reg_form.addButton('Cancel', function(){ reg_form.reset(); });

Ещё я хочу перехватывать события формы, и соответственно реагировать на успешное завершение регистрации и ошибки. Для этого я прикрепляю свои обработчики к событиям формы actioncomplete и actionfailed, причем за первое отвечает моя функция, а второе описано просто в коде, выдавая сообщение об ошибке. Посмотрим, как это реализовано:

reg_form.on('actioncomplete', register_complate);

reg_form.on('actionfailed', function(){  Ext.MessageBox.alert('Ошибка!', 'Ошибка в процессе регистрации пользователя! Может, неверный BetaKEY?');});

Сама функция отправки данных очень проста. Сначала мы проверяем, верно ли заполнены все поля формы, для чего опрашиваем метод isValid формы, и в случае возврата true, отправляем форму методом submit. А в случае неверного заполнения вызываем метод, который отмечает все неверно заполненные поля.

function form_data_eval()

{

    if (reg_form.isValid() == true)

        {

            reg_form.submit();

        }

    else

        {

            reg_form.markInvalid();

            Ext.MessageBox.alert('Ошибка!', 'Ошибка, информация неверная!');

        }

}

Обработка actioncomplete простая и заключается в выводе приветственного сообщения через функцию alert(). А вы можете подставить свою код.

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

  1. alex
    10 февраля 2008 в 18:03 | #1

    и нифига не пашет

  2. 10 февраля 2008 в 18:31 | #3

    что именно? знаете, чем отличается программист от остальных? либо вы конкретно напишите, что вы делаете, как и что именно не работает или работает по другому, нежели ожидается, тогда можно вам что-то подсказать. либо может стоит начать с чего-то более простого, чем сразу AJAX и ExtJS? как минимум с отладки и понимания работы AJAX веб-приложений.

  3. sergey
    11 февраля 2008 в 15:07 | #4

    Почему в API нет Ext.form.Form? Это пример со старой библиотекой, что ли? Сейчас я вижу Ext.form.FormPanel. Наверное другая реализация. Хотелось бы пример.

  4. 11 февраля 2008 в 15:29 | #5

    Ну, если внимательно читать, то да, написано в самом начале.. «Замечу, что основываться мы будем на версии ExtJS 1.1.1…». На 2.0 я пытался сейчас делать новый проект, но так как с ней нужно больше разбираться, то решили сделать на уже изученной 1.1.1. Посмотрите Migration Guide на сайте, увидите что изменилось.

  5. 11 февраля 2008 в 15:30 | #6

    как то все же соберусь плотно изучить 2.0, тогда напишу

  6. Sergey
    11 февраля 2008 в 16:22 | #7

    Взял их пример с формой. Взял пример Desctop. Пробую отобразить на рабочем столе, форма получается искаженной. Только в IE нормально. Куда копать?

  7. 11 февраля 2008 в 16:25 | #8

    Desktop как я помню, вроде в 2.0 пример появился.
    а сами то примеры по отдельности работают? те которые идут в дистрибутиве?

    Смотреть что значит искажет, смотреть фаербугом что не так., все ли подключается, все стили, пути и т.д.

  8. Sergey
    11 февраля 2008 в 16:37 | #9

    Да, примеры работают. Если я в body рендерю, то форму вообще не видно. Видно слои рабочего стола перекрывают(я еще в firebug посмотрю), а если в div id=x-desctop, то форма искажается.

    И еще вопрос, не могу понять что в библиотеке имеется ввиду под понятием layout?

  9. 11 февраля 2008 в 16:46 | #10

    значит трабла именно в совместимости, возможно в перекрытии слоев/стилей.

    в боди рендерить не надо тогда точно ничего не будет.

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

  10. Sergey
    11 февраля 2008 в 17:20 | #11

    Добавил в div рабочего стола ещё , и в него рендерю. Теперь нормально. Там ярлыки мешали со своими дивами. Теперь бы спозиционировать по центру.
    Я, собственно, думал, что форма сама отрисуется как, например, алерты. Т.е, чтоб не привязывать к конкретному узлу. В общем, еще мало понимаю. уду копаться.

  11. Sergey
    13 февраля 2008 в 10:40 | #12

    Нет ссылки на исходники. Хочется посмотреть подробнее.

  12. 13 февраля 2008 в 11:41 | #13

    каких где исходников? Ext-a есть 🙂

  13. Sergey
    13 февраля 2008 в 13:27 | #14

    Например, как вытащить данные из response. В примере ничего не сказано. Пришлось копаться. И много других мелочей, которые для автора понятны, а начинающий непонимает о чем идет речь.

  14. Sergey
    13 февраля 2008 в 14:08 | #15

    Кстати вопрос. Приходит success:false, допустим неправильный пароль. Почему форма маркирует первое поле name и вставляет подсказку. Как с этим бороться?

  15. Sergey
    13 февраля 2008 в 14:43 | #16

    А, извиняюсь, во второй части вычитал

  16. 13 февраля 2008 в 17:02 | #17

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

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

  17. Vasy@
    19 февраля 2008 в 15:11 | #18

    reg_form.isValid — в 1.1 есть, а в 2.0 нет, Что делать ?
    Пробовал reg_form.user_password
    if (reg_form.user_password.isValid() == true)
    {
    user.submit();
    }

    НО тоже не получилось — reg_form.user_password has no properties.

    В чём ошибка ?

  18. 19 февраля 2008 в 15:16 | #19

    есть в классе Ext.form.BasicForm либо использовать мониторинг с класса FormPanel

  19. Vasy@
    19 февраля 2008 в 16:07 | #20

    Вот тут разобрался
    http://extjs.com/learn/Tutorial:Basic_Login

    Надо было работать с reg_form.getForm().submit

  20. 19 февраля 2008 в 18:57 | #21

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

  21. Прохожий
    16 мая 2008 в 08:20 | #22

    Все же ориентироваться на старую библиотеку смысла нет

  22. 3 августа 2008 в 18:56 | #23

    Спасибо за ответы на все вопросы 🙂 На самом деле узнал много нового. Вот только до конца так и не разобрался что и откуда.

  23. 15 декабря 2011 в 15:34 | #24

    а где скачать можно что получилось в итоге?

  24. Андрей
    12 января 2013 в 06:06 | #25

    Спасибо автору,- хорошая статья! Вот тут есть перевод документации по Ext JS на русский http://phpshnik.ru/ext-js-4/rukovodstvo

Комментирование отключено.