Статьи

Baby Steps для Backbone.js: проверка модели

Давайте на минуту вернемся к предыдущему посту, где мы начали загружать некоторые базовые приложения Backbone.js. Теперь это очень просто, просто собирая все данные и отправляя данные на сервер.

Любая надежная система практически невозможна без проверки. Если какое-либо поле является обязательным или должно соответствовать какому-либо конкретному правилу, оно должно быть проверено как можно скорее, и информация о проверке должна отображаться пользователю. Затем пользователь применяет исправления и повторно представляет данные.

В случае модели «Обратная связь», мы заинтересованы, чтобы пользователь всегда вводил свою электронную почту и сообщение обратной связи. Backbone.js предоставляет очень простой способ проверки моделей. Если модель требует проверки, она должна реализовать метод проверки .

Итак, давайте расширим нашу модель методом validate.

var Feedback = Backbone.Model.extend({
    url: '/feedback',

    defaults: {
        'email': '',
        'website': '',
        'feedback': ''
    },

    validate: function (attrs) {
        if (!attrs.email) {
            return 'Please fill email field.';
        }
        if (!attrs.feedback) {
            return 'Please fill feedback field.';
        }
    }
});

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

Чтобы лучше понять, что происходит, давайте рассмотрим некоторый фрагмент кода из инфраструктуры Backbone.js. А именно, для `_validate` метода` Backbone.Model`, который фактически отвечает за проверку.

_validate: function(attrs, options) {
    if (options.silent || !this.validate) return true;
    attrs = _.extend({}, this.attributes, attrs);
    var error = this.validate(attrs, options);
    if (!error) return true;
    if (options && options.error) {
       options.error(this, error, options);
    } else {
        this.trigger('error', this, error, options);
    }
    return false;
}

Вы можете видеть, что если `validate` возвращает либо undefined, либо null, либо false,` _validate` просто возвращает true — это значит, что модель действительна. В противном случае он проверил бы, инициализирована ли функция `options.error`, и вызвал бы ее, если не было вызвано событие модели` error`.

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

var options = {
    success: function () {
        alert('Thanks for the feedback!');
    },
    error: function (model, error) {
        alert(error);
    }
};

var feedback = {
    email: this.$('#email').val(),
    website:  this.$('#website').val(),
    feedback: this.$('#feedback').val()
};

this.model.save(feedback, options);

Обратите внимание, что обратный вызов `error` получает саму модель в качестве первого аргумента, а объект ошибки (один возвращается из метода` validate`) в качестве второго аргумента. Давайте попробуем этот код: оставьте поля электронной почты и обратной связи пустыми и нажмите кнопку отправки.

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

Таким образом, мы должны сделать 2 вещи: собрать все ошибки во время проверки и применить к ним несколько хороших стилей.

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

validate: function (attrs) {
    var errors = [];

    if (!attrs.email) {
        errors.push({name: 'email', message: 'Please fill email field.'});
    }
    if (!attrs.feedback) {
        errors.push({name: 'feedback', message: 'Please fill feedback field.'});
    }

    return errors.length > 0 ? errors : false;
}

Измените параметры метода `save`, чтобы отображать ошибки, если возникла какая-либо ошибка, и скрывать ошибки, если сохранение прошло успешно.

var me = this;
var options = {
    success: function () {
        me.hideErrors();
    },
    error: function (model, errors) {
        me.showErrors(errors);
    }
};

И реализовать 2 простых метода:

showErrors: function(errors) {
    _.each(errors, function (error) {
        var controlGroup = this.$('.' + error.name);
        controlGroup.addClass('error');
        controlGroup.find('.help-inline').text(error.message);
    }, this);
},

hideErrors: function () {
    this.$('.control-group').removeClass('error');
    this.$('.help-inline').text('');
}

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

По мере заполнения полей и отправки формы все ошибки удаляются из формы.

Выводы

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

Оставайтесь с нами для следующих шагов ребенка Backbone.js скоро.