Разработка с AngularJS: создание форм

Всем привет! Как и обещал, вот продолжение материала о работе с AngularJS. На этот раз речь пойдет о том, как можно избавиться от шаблонного кода в своем проекте.

Основы подхода

AngularJS — фреймворк, который очень хорошо поддерживает модульную структуру, что позволяет писать независимые модули. Давайте разберем на примере форм. Что необходимо для работы форм:

  1. View — отображение наших полей
  2. Validation — проверка введенных данных
  3. Обработка данных

Первые два пункта будут повторятся из проекта в проект, 90% форм выглядят одинаково. Давайте тогда выделим форму в компонент, который будет заниматься отображением и валидацией. Компонент, который будет отвечать за валидацию, возьмем из нашего репозитория. Генератор формы можно разделить на 2 модуля:

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

Данные для генерации я предлагаю описать в такой структуре:

this.model = {
            url: 'sign-in',
            submit: function (data) {

            },
            rules: {
                email: {
                    type: 'invalid',
                    message: 'Email error',
                    rule: function (form, field) {
                        var re = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
                        return field.$dirty && !re.test(field.$modelValue);
                    }
                }
            },
            attr: {
                identifier: {
                    type: 'text',
                    attr: {placeholder: 'Ваш email или номер телефона'},
                    validators: ['required', 'email']
                },
                gender: {
                    type: 'select',
                    value: 'man',
                    options: [{
                        name: 'Man',
                        value: 'man'
                    }, {
                        name: 'Woman',
                        value: 'woman'
                    }],
                    attr: {placeholder: 'Ваш email или номер телефона'},
                    validators: ['required']
                },
                password: {
                    type: 'password',
                    attr: {placeholder: 'Ваш пароль'},
                    validators: ['required']
                }
            },
            buttons: {
                submit: {
                    text: "Войти"
                }
            }
        };

Rules позволяет задать кастомный валидатор, attr хранит список наших полей. Ну а сама форма будет инициализироваться путем вызова директивы:

body
        div(ng-controller="demoCtrl as ctrl")
            mgr-form-builder(model="ctrl.model")

Возможно, у многих возникнет вопрос: «Как кастомизировать View для какой-то уникальной формы?». Для этого достаточно передать URL нового шаблона формы через атрибут templateUrl:

scope: {
                model: '=',
                formName: '=',
                templateUrl: '@'
            },
            templateUrl: function (el, attr) {
                if (attr.templateUrl) {
                    return attr.templateUrl;
                }
                return 'formBuilder/formBuilder.html';
            },

После того, как с отображением стало почти все ясно, возникает вопрос: как теперь получить данные после успешного заполнения формы? Добавим функцию, которая будет отрабатывать по событию submit:

formBuilderCtrl.submit = function () {

                    if (!formBuilderCtrl.model.submit) {
                        return false;
                    }

                    var data = {};
                    Object
                        .keys(formBuilderCtrl.model.attr)
                        .forEach(function (key) {
                            data[key] = formBuilderCtrl.model.attr[key].value;
                        });

                    formBuilderCtrl.model.submit(data);
                };

Теперь достаточно только указать нашу функцию в модуле. Как только форма будет успешно заполнена, у нас сработает функция submit, в которую будет переданы значения, введенные пользователем.

Результат

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