Отображение ошибок валидации

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

Стандартно, Symfony проверяет все ошибки в передаваемой форме и выводит их списком над полем где эти ошибки случились. Что если я хочу показывать только одну? На помощь может придти креативный подход к делу, а именно:

  • Накатать partial для вывода, где поле за полем будет выводится форма и только одна ошибка для него, первая.
  • Выводить все ошибки как есть, и гасить их каким-нибудь Javascript’ом
  • Колдовать со списками ошибок на CSS и в итоге получить не совсем кроссбраузерное решение

Всё это можно, но не так интересно программисту, как покопаться во фреймворке и найти способ поизящнее. Я начал искать в классах sfForm, sfWidget и так далее. Нашёл откуда ростут ноги у ошибок и куда они складываются. Обнаружились они в массивах $errors повсеместно в классе sfWidgetFormSchemaFormatter. Массив этот проходит обработку методом unnestErrors. Я решил убить двух зайцев сразу, сделав во-первых своё custom-форматирование полей, во вторых избавиться от лишних ошибок переписав unnestErrors.

Насмотревшись вдоволь на поставляемые с симфонией два шаблона отображения форм я выбрал что-то среднее между ними обоими. Поля будут в табличке, а ошибки в теге span сразу за полями. На span я поставлю стиль position: absolute чтобы их положение никак не влияло на остальную вёрстку и не увечила форму. Я так хочу, ибо не люблю пляшущих форм.

Создаю свой formatter в файле lib/widget/sfWidgetFormSchemaFormatterMy.class.php

class sfWidgetFormSchemaFormatterMy extends sfWidgetFormSchemaFormatter
{

   protected
     $rowFormat       = "<tr>\n  <th>%label%</th>\n  <td>%field%%error%%help%%hidden_fields%</td>\n</tr>\n",
     $errorRowFormat  = "",
     $helpFormat      = '<br />%help%',
     $decoratorFormat = "",
     $errorListFormatInARow     = "%errors%",
     $errorRowFormatInARow      = "<span class=\"error\">← %error%</span>\n",
     $namedErrorRowFormatInARow = "<span class=\"error\">← %name%: %error%</span>\n";

Добавляю обещанный удар серпом по ошибкам валидации.

function  unnestErrors($errors, $prefix = '')
{
  $newErrors = parent::unnestErrors($errors, $prefix);
  $newErrors = array_slice($newErrors, 0,1);
  return $newErrors;
}

Здесь остаётся только первая ошибка для каждого поля. Если вам стало не понятно, посмотрите методsfWidgetFormSchemaFormatter::unnestErrors где происходит основное действо.

Добавляю CSS для красивости:

.error {
  position: absolute;
  color: red;
  padding: 8px;
  background: white;
  border-radius: 5px;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
}

Проверяю как всё работает.

Было:

Стало:

Кажется, получилось очень даже аппетитно. Всё, что мне нужно теперь чтобы форма выглядела так, это добавить в класс формы одну строчку:

$this->getWidgetSchema()->setFormFormatterName('my');

оригинал

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: