Reputation: 13321
I'd like to display errors on my form, highlighting the fields which have errors, and displaying the error text next to the field. If there's no elegant way to display next to each field, above would be fine.
I've found examples from earlier versions, but the API has seemed to change and they do not work for 3.2.
It's just a project I'm learning Kohana with, so it's not critical. I just want to know the "kohana" way of handling this problem.
In my controller, I have this:
if (isset($_POST) && Valid::not_empty($_POST))
{
$post = Validation::factory($_POST)
->rule('zipcode', 'not_empty'));
if ($post->check()) {
$errors = $post->errors('zipcode');
}
}
$this->template->content = View::factory('myview', $data)
->bind('errors', $errors);
And here is my form in 'myview.php':
<?php echo Form::open(); ?>
<dl>
<dt><?php echo Form::label('zipcode', 'Zip Code') ?></dt>
<dd><?php echo Form::input('zipcode') ?></dd>
</dl>
<p><?php echo Form::submit(NULL, 'Get Records'); ?></p>
<?php echo Form::close(); ?>
Upvotes: 0
Views: 2897
Reputation: 9650
I've taken the approach of extending the Form helper class to add an 'error' class name on the form fields, as well as showing the error message in the field label.
<?php defined('SYSPATH') or die('No direct script access.');
class Form extends Kohana_Form {
private static function attributes($name, & $attributes = NULL, $errors = NULL)
{
// Set the id attribute
if (!isset($attributes['id']))
{
$attributes['id'] = $name;
}
if ($errors !== NULL)
{
// Merge in external validation errors.
$errors = array_merge($errors, (isset($errors['_external']) ? $errors['_external'] : array()));
// Set the error classname
if (isset($errors[$name]))
{
$attributes['class'] = trim( (string) @$attributes['class'].' error-field');
}
}
}
public static function input($name, $value = NULL, array $attributes = NULL, array $errors = NULL)
{
static::attributes($name, $attributes, $errors);
return parent::input($name, $value, $attributes);
}
public static function select($name, array $options = NULL, $selected = NULL, array $attributes = NULL, array $errors = NULL)
{
static::attributes($name, $attributes, $errors);
return parent::select($name, $options, $selected, $attributes);
}
public static function password($name, $value = NULL, array $attributes = NULL, array $errors = NULL)
{
static::attributes($name, $attributes, $errors);
return parent::password($name, $value, $attributes);
}
public static function textarea($name, $body = '', array $attributes = NULL, $double_encode = TRUE, array $errors = NULL)
{
static::attributes($name, $attributes, $errors);
return parent::textarea($name, $body, $attributes, $double_encode);
}
public static function file($name, array $attributes = NULL, array $errors = NULL)
{
static::attributes($name, $attributes, $errors);
return parent::file($name, $attributes);
}
public static function label($input, $text = NULL, array $attributes = NULL, array $errors = NULL, $view = 'messages/label_error')
{
if ($errors !== NULL)
{
// Merge in external validation errors.
$errors = array_merge($errors, (isset($errors['_external']) ? $errors['_external'] : array()));
// Use the label_error view to append an error message to the label
if (isset($errors[$input]))
{
$text .= View::factory($view)->bind('error', $errors[$input]);
}
}
return parent::label($input, $text, $attributes);
}
}
You then pass in the $errors
array into the label and field helper methods:
<?php echo
Form::label('username', 'Username', NULL, $errors),
Form::input('username', $user->username, NULL, $errors);
?>
This idea was suggested on the Kohana forums but I've struggled to find the original thread. Anyway, I've found this approach works best for me.
[edit] View an example of this approach in action here: http://kohana3.badsyntax.co/contact (submit the form)
Upvotes: 3
Reputation: 8010
This is some sample code I have used for a personal experiment with Kohana forms. It is part of a contact form. This should work for you.
The code below shows a contact form. After a user submits the form, it gives feedback (failed + errors / succeed).
if (isset($errors) && count($errors) > 0)
{
echo '<ul>';
foreach ($errors as $error)
{
echo '<li>' . $error . '</li>';
}
echo '</ul>';
}
// form
echo Form::open(null);
// fields
echo Form::label('firstname') . Form::input('firstname', null, array('id' => 'firstname')) . '<br />';
echo Form::label('email') . Form::input('email', null, array('id' => 'email')) . '<br />';
echo Form::label('message') . Form::textarea('message', '', array('id' => 'message')) . '<br />';
// submit
echo Form::submit('submit', 'Send message');
echo Form::close();
In the controller, I validate the form and assign the error- and success messages to the view.
public function action_index()
{
// make view
$view = View::factory('pages/contact')
->bind('post', $post)
->bind('errors', $errors)
->bind('success', $success);
// check if form is submitted
if ($_POST)
{
// trim fields
$post = array_map('trim', $_POST);
$post = Validation::factory($_POST)
->rules('firstname', array(
array('not_empty'),
array('min_length', array(':value', '2'))
))
->rules('email', array(
array('not_empty'),
array('email')
))
->rule('message', 'not_empty');
if ($post->check())
{
$success[] = 'Thank you for your message!';
}
else
{
$errors = $post->errors('contact');
}
}
// view
$this->response->body($view);
}
I hope this helps!
Upvotes: 0