Reputation: 53
I'm building a form using Laravel 4 and Twitter Bootstrap 3 and I want to error messages to appear next to the field. This is the solution that I came up with but it ends up being 15 lines of code per field.
@section('content')
<div class="container">
<h1>Edit User</h1>
{{ Form::model($user, array('route' => array('users.update', $user->id), 'method' => 'PUT', 'class' => 'form-horizontal')) }}
{{-- First Name field --}}
{{-- Start a form group. If there any errors, then highlight the field red. --}}
<div class="form-group {{ $errors->has('first_name') ? 'has-error' : '' }}">
{{-- Display the label and the field. --}}
{{ Form::label('first_name', 'First Name', array('class' => 'col-sm-2 control-label')) }}
<div class="col-sm-5">
{{ Form::text('first_name', NULL, array('class' => 'form-control', 'placeholder' => 'First Name')) }}
</div>
{{-- If there is an error, display any messages to the right of the field with a warning icon. --}}
@if($errors->has('first_name'))
<div class="col-sm-5">
@foreach ($errors->get('first_name') as $message)
<span class="help-block">
<span class="glyphicon glyphicon-warning-sign"></span>
{{ $message }}
</span>
@endforeach
</div>
@endif
</div>
{{-- Form buttons --}}
<div class="form-group">
{{-- Line up the buttons with the right edge of the fields. --}}
<div class="col-sm-offset-2 col-sm-5">
<div class="pull-right">
{{-- Cancel button takes user back to profile page. --}}
{{ HTML::linkRoute('users.show', 'Cancel', array($user->id), array('class' => 'btn btn-default')) }}
{{ Form::submit('Submit', array('class' => 'btn btn-primary')) }}
</div>
</div>
</div>
{{ Form::close() }}
</div>
@stop
This is how it appears:
I'm just starting out with both Laravel and Bootstap. I used Jeffery Way's tutorial on NetTuts to make the form and Coder's Guide's tutorial to apply the formatting.
Should I be using client-side validation or would this be considered an acceptable implementation of Laravel 4 and Bootstrap?
Thanks!
Upvotes: 3
Views: 4178
Reputation: 3855
This may not be the coolest way to do this but I think it's pretty slick.
Laravel has a feature called Form::macro
that allows you to sort of make reusable code snippets. You can define a macro all kinds of places but I just slapped mine in my routes.php
file to get this going real quick.
Form::macro('errorMsg', function($field, $errors){
if($errors->has($field)){
$msg = $errors->first($field);
return "<span class=\"error\">$msg</span>";
}
return '';
});
Then to use in a form, pass the macro your error messages:
{{ Form::label('first_name', 'First Name:') }}
{{ Form::text('first_name') }}
{{ Form::errorMsg('first_name', $errors) }}
{{-- where $errors is your Illuminate\Support\MessageBag object --}}
To get even more tech, you can use Form::objects
in a Form::macro
like so:
Form::macro('textError', function($field, $label, $errors){
$label_html = Form::label($field, $label);
$text_html = Form::text($field);
$msg_html = '';
if($errors->has($field)){
$msg_html.= '<span class="error">';
$msg_html.= $errors->first($field);
$msg_html.= '</span>';
}
return $label_html.$text_html.$msg_html;
});
Then you're at 1
line per input:
{{ Form::textError('first_name', 'First Name:', $errors) }}
You'd need to make other macros for password, textarea, etc. (which is why I just use the first example; it's only a couple more lines of code per input and serves all input types.)
If you wanted to style your input on error, eg. a red border, you'd probably want the second example then wrap it in your div.form-group
or whatevers. Anyway, options out the wazoo.
UPDATE: An even slicker way to get errors in macros is to access them via Session::get('errors');
like so:
Form::macro('errorMsg', function($field){//yay! we don't have to pass $errors anymore
$errors = Session::get('errors');
if($errors && $errors->has($field)){//make sure $errors is not null
$msg = $errors->first($field);
return "<span class=\"error\">$msg</span>";
}
return '';
});
Upvotes: 9