Combine Form::text and error check into one? - laravel

In the blade view file, I have something like this:
{{ Form::text('contact_name', null, ['class' => 'form-control']) }}
#if ($errors->has('contact_name'))
<div class="error-block">{{ $errors->first('contact_name') }}</div>
#endif
{{ Form::text('contact_email', null, ['class' => 'form-control']) }}
#if ($errors->has('contact_email'))
<div class="error-block">{{ $errors->first('contact_email') }}</div>
#endif
When user press submit, it will check inputs validation in the controller. However, if there is an error with the validation, it will then redirect back to a form and populate it with error messages {{ $errors->first() }}
Is there a way to exclude {{ $errors->first() }} in the view file and still show error messages if validation failed? So combine Form::text and $errors->hasinto one function or something like that?

Use a Form Macro to do this
Form::macro('myText', function($field)
{
$string = Form::text($field, null, ['class' => 'form-control']);
if ($errors->has($field)) {
$string .= $errors->first($field);
}
return $string;
});
Then in your view
{{ Form::myText('contact_email') }}

Related

proper usage of forms with routes in laravel 4.2

i have this form in view:
{{ Form::open(array('action' => 'StudentrecordController#viewSRS')) }}
<span><strong>Select School Year & Quarter</strong></span>
<div class="form-group">
{{ Form::select('sy', [null=> 'Select School Year'] + $schoolYearID , Input::old('modules'), array('class'=>'form-control') ) }}
</div>
<div class="form-group">
{{ Form::select('sq', [null=> 'Select Quarter'] + $schoolQuarterID , Input::old('modules'), array('class'=>'form-control') ) }}
</div>
{{ Form::submit('Sort', array('class' => 'btn btn-primary')) }}
{{ Form::close() }}
my route for this is
Route::get('sortsRec', 'StudentrecordController#viewSRS');
when i clicked the submit button it gives out a method not allowed exception.i think the form is sending out a post method but the route accepts get. how can i address this? any idea what i can do?
By default, a POST method will be assumed; however, you are free to specify another method:
{{ Form::open(['method' => 'get', 'action' => 'StudentrecordController#viewSRS']) }}
From the docs.

Combine all NotBlank error messages in Symfony2

I'm trying to combine all NotBlank error messages into one.
If the error array contains at least 1 error that is a NotBlank type, I want it to display only one message like "Please fill in all fields."
How can I do this?
Here's my twig code
{{form_start(form, {'attr': {'novalidate': 'novalidate'}})}}
<div>
{{form_widget(form.firstName)}}
{{form_widget(form.lastName)}}
</div>
<div>
{{form_widget(form.username)}}
{{form_widget(form.email)}}
</div>
<div>
{{form_widget(form.password.first, {'attr' : { 'placeholder' : 'Password' } })}}
{{form_widget(form.password.second, {'attr' : { 'placeholder' : 'Confirm Password' } })}}
</div>
<div>
{{form_label(form.birthday)}}
</div>
<div>
{{form_widget(form.birthday)}}
</div>
<div>
{{form_widget(form.gender)}}
</div>
<div>
{{form_widget(form.save)}}
</div>
{{ form_errors(form.firstName) }}
{{ form_errors(form.lastName) }}
{{ form_errors(form.username) }}
{{ form_errors(form.email) }}
{{ form_errors(form.password.first) }}
{{form_end(form)}}
You can create a CallbackValidator
http://symfony.com/doc/current/reference/constraints/Callback.html
and in the validate method, check if at least one of the desired fields is blank, and if true, call
/**
* #Assert\Callback
*/
public function validate(ExecutionContextInterface $context)
{
if(empty($this->field1) || empty($this->field2)) {
$context->addViolation($message);
}
}
This way you will receive a global form error.

Laravel pre-filling multiple forms if validation failed

One of the coolest Laravel feature is, Laravel pre-filled the form fields if validation error occurred. However, if a page contain more than one form, and form fields have same name, Laravel pre-filling all forms fields.
For example:
I have a page where i have two forms to create new users or whatever.
<h1>Create user1</h2>
{{ Form::open(array('url' => 'foo/bar')) }}
{{ Form::text('name', null) }}
{{ Form::email('email', null) }}
{{ Form::close() }}
</h1>Create user2</h1>
{{ Form::open(array('url' => 'foo/bar')) }}
{{ Form::text('name', null) }}
{{ Form::email('email', null) }}
{{ Form::close() }}
Controller
class UsersController extends BaseController
{
public function store()
{
$rules = [
'name' => 'required',
'email' => 'required'
];
$validation = Validator::make(Input::all(), $rules);
if ($validation->fails()) {
return Redirect::back()->withInput()->withErrors($validation);
}
}
}
As i didn't fill up the email, Laravel will throw validation error and pre-filling the forms as following:
How to tell Laravel that do not fill-up the second form?
There's no Laravel way of doing this, but you can use HTML basic form arrays to make it work. You need to understand that you have to identify your forms and fields so Laravel knows exactly where the data came from and where to send it back to. If all your fields have the same name how could it possibly know?
This is a proof of concept that will work straight from your routes.php file.
As I did it all and tested here before posting the answer I used Route::get() and Route::post(), to not have to create a controller and a view just to test something I will not use. While developing this you will have to put this logic in a controller and in a view, where I think they are alredy in.
To test it the way it is, you just have to point your browser to the following routes:
http://yourserver/form
and when you push a button it will automatically POST tho the route:
http://yourserver/post
I'm basically giving all forms a number and giving the buttons the number that we will usin in Laravel to get the form data and validate it.
Route::get('form', function()
{
return Form::open(array('url' => URL::to('post'))).
Form::text('form[1][name]', null).
Form::email('form[1][email]', null).
'<button type="submit" name="button" value="1">submit</button>'.
Form::close().
Form::open(array('url' => URL::to('post'))).
Form::text('form[2][name]', null).
Form::email('form[2][email]', null).
'<button type="submit" name="button" value="2">submit</button>'.
Form::close();
});
And here we get the data, select the form and pass all of it to the validator:
Route::post('post', function()
{
$input = Input::all();
$rules = [
'name' => 'required',
'email' => 'required'
];
$validation = Validator::make($input['form'][$input['button']], $rules);
return Redirect::back()->withInput();
});
This is how you use it in a Blade view, now using 3 forms instead of 2 and you can have as many forms as you need:
<h1>Create user1</h2>
{{ Form::open(array('url' => URL::to('post'))) }}
{{ Form::text('form[1][name]', null) }}
{{ Form::email('form[1][email]', null) }}
<button type="submit" name="button" value="1">submit</button>
{{ Form::close() }}
</h1>Create user2</h1>
{{ Form::open(array('url' => URL::to('post'))) }}
{{ Form::text('form[2][name]', null) }}
{{ Form::email('form[2][email]', null) }}
<button type="submit" name="button" value="2">submit</button>
{{ Form::close() }}
</h1>Create user3</h1>
{{ Form::open(array('url' => URL::to('post'))) }}
{{ Form::text('form[3][name]', null) }}
{{ Form::email('form[3][email]', null) }}
<button type="submit" name="button" value="3">submit</button>
{{ Form::close() }}
And you can even use a loop to create 100 forms in blade:
#for ($i=1; $i <= 100; $i++)
User {{$i}}
{{ Form::open(array('url' => URL::to('post'))) }}
{{ Form::text("form[$i][name]", null) }}
{{ Form::email("form[$i][email]", null) }}
<button type="submit" name="button" value="{{$i}}">submit</button>
{{ Form::close() }}
#endfor
Use old input with $request->flash().
https://laravel.com/docs/5.2/requests#old-input

Laravel 4 blade drop-down list class attribute

Laravel blade drop down list class attribute not working.
I cannot find any reference to class or assigning attributes to select / drop-down lists in the documentation.
http://www.laravel.com/docs/html#drop-down-lists
Examples tried:
{{ Form::select('product_id', $productList, array('class'=>'form-control')) }}
{{ Form::select('product_id', $productList, $attributes = array('class'=>'form-control')) }}
Both return the same html but without the class attribute:
<select id="product_id" name="product_id">
... Option Stuff ...
</select>
{{ Form::select('product_id', $productList, null, array('class' => 'form-control')) }}
The third parameter is the key of the currently selected option. Defaults to null.
First get and create list in Controller for example:
$username_lists = Users::lists('username','id');
pass data to view by:
return View::make('layouts.customers')
->with('username_lists', $username_lists);
now get in view:
{{ Form::select('username_lists', $username_lists, null, array('class' => 'form-control')) }}

Laravel - highlighting the confirmation field for an error

I can't find a way to get Laravel to highlight the correct field when a _confirmation field is incorrect.
Using a Bootstrap layout I've got an email and email_confirmation field in my form like this:
<div class="control-group {{$errors->has('email') ? 'error' : ''}}">
{{ Form::label('email', 'Email', array('class' => 'control-label'))}}
<div class="controls">
{{ Form::email('email', Input::old('email'));}}
{{ $errors->first('email', Form::block_help(':message')) }}
</div>
</div>
<div class="control-group {{$errors->has('email_confirmation') ? 'error' : ''}}">
{{ Form::label('email_confirmation', 'Confirm Email', array('class' => 'control-label'))}}
<div class="controls">
{{ Form::email('email_confirmation', Input::old('email_confirmation'));}}
{{ $errors->first('email_confirmation', Form::block_help(':message')) }}
</div>
</div>
So if the user puts in an invalid email address then the 'email' field will have an error attached to it and the correct label/field will be highlighted.
But if the user has entered a valid/correct email address in the first field but gets the confirmation wrong - the error returned is still for the 'email' field, not the email_confirmed field.
To me it looks weird when the email field is highlighted when the error is actually with the email_confirmation field.
As far as I can understand from this stackoverflow question, I could probably do something like
{{$errors->first('email', ':message') == 'Please confirm your email address correctly.' ? 'error' : ''}}
This will work, but the problem is that I'm running a multi-lingual site so the :message that gets returned is going to be one of many possibilities.
I guess I could write a function to compare the :message against an array of messages for each language but I thought I'd check if there was an easier way to go about it.
Cheers!
This is how I show an inline error if the title field is empty:
<div class="form-group #if ($errors->has('title')) has-error #endif">
{{ Form::label('title', 'Title') }}
{{ Form::text('title', null, array('class' => 'form-control')) }}
#if ($errors->has('title')) <p class="help-block">{{ $errors->first('title') }}</p> #endif
</div>
And my validation rule:
public static $rules = array(
'title' => 'required',
);
Using Laravel 4 and Bootstrap 3.
Or you could just print all the Error messages somewhere
$messages = $validator->messages();
echo '<ul>';
foreach ($messages->all() as $message)
{
echo '<li>'.$message.'</li>';
}
echo '</ul>';

Resources