In Laravel how to show error message beside specific field? - laravel

I am new to laravel. I created a simple page where a user can add a product to the database. If the product title or amount is empty; I can also show the errors. But I want to show error right beside the specific field. If the title is empty the error will show beside the title field.
I searched and found solutions using JS and some other. But is there a way to achieve this using only laravel?
my view is like this
<form method="POST" action="create">
#csrf
<input type="text" name="title" placeholder="Product name"><br>
<textarea name="description" placeholder="Description"></textarea><br>
<input type="string" name="amount" placeholder="Price per unit"><br>
<button type="submit">Add Product</button>
</form>
#if(count($errors))
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
#endif
and my controller is like this
public function store()
{
$this->validate(request(),[
'title'=> 'required',
'amount' => 'required',
]);
$product = new Product;
$product->title = request('title');
$product->seller_id = Auth::guard('seller')->user()->id;
$product->description = request('description');
$product->amount = request('amount');
$product->save();
return redirect('/dashboard');
}

You need to check for errors and display wherever you want like given below
#if ($errors->has('title')) <p style="color:red;">{{ $errors->first('title') }}</p> #endif
and
#if ($errors->has('amount')) <p style="color:red;">{{ $errors->first('amount') }}</p> #endif
In your code for view it can be placed as
<form method="POST" action="create">
#csrf
<input type="text" name="title" placeholder="Product name">
#if ($errors->has('title')) <p style="color:red;">{{ $errors->first('title') }}</p> #endif <br>
<textarea name="description" placeholder="Description"></textarea><br>
<input type="string" name="amount" placeholder="Price per unit">
#if ($errors->has('amount')) <p style="color:red;">{{ $errors->first('amount') }}</p> #endif <br>
<button type="submit">Add Product</button>
</form>
Additionally you can also print custom messages by returning the error text from controller as shown below
$customMessages = [
'title.required' => 'The title field is required to be filled',
'amount.required' => 'The amount field should be completely filled'
];
$this->validate(request,[
'title'=> 'required',
'amount' => 'required',
], $customMessages);
Instead, if you want to show all the errors for a field you can print them as follows
#if ($errors->has('title'))
<p style="color:red;">
#foreach ($errors->get('title') as $errormessage)
{{ $errormessage }}<br>
#endforeach
</p>
#endif

All errors you can get in $errors array
just get them by input field name
Example:
<div class="form-group {{ $errors->has('title') ? 'has-error' : ''}}">
<label for="titile" class="col-sm-3 control-label">Title: </label>
<div class="col-sm-6">
<input class="form-control" placeholder="Product name" required="required" name="title" type="text" id="title">
{!! $errors->first('title', '<p class="help-block">:message</p>') !!}
</div>
</div>
Here, $errors->first('title') mean its getting the first index of title errors in $errors array.
in your view you can do this as:
<form method="POST" action="create">
#csrf
<input type="text" name="title" placeholder="Product name"><br>
{!! $errors->first('title', '<p class="help-block">:message</p>') !!}
<br>
<textarea name="description" placeholder="Description"></textarea><br>
{!! $errors->first('description', '<p class="help-block">:message</p>') !!}
<br>
<input type="string" name="amount" placeholder="Price per unit"><br>
{!! $errors->first('amount', '<p class="help-block">:message</p>') !!}
<br>
<button type="submit">Add Product</button>
</form>

Related

Laravel 8 - All validation rules are shown if one rule applies

I am using Laravel Framework 8.62.0 and I am having the following validation rules:
$rules=[
'username' => 'required|min:3|max:30|alpha_dash',
'email' => "required|email|unique:users,email",
'password' => 'required|min:6|confirmed',
];
$error_messages=[
'username.required'=>'The username-field is required.',
'username.min'=>'Your username must be longer than 3 characters.',
'username.max'=>'Please shorten your username.',
'username.alpha_dash'=>'Please use letters from A-Z and a-z, dashes (-) or underscores(_).',
'email.unique'=>'Your email is already used.',
'email.email'=>'Please add a correct email-address.',
'email.required'=>'The email-field is required.',
'password.required'=>'The password-field is required.',
'password.min'=>'Your password must have at least 6 characters.',
'password.confirmed'=>'Your entered passwords do not match.',
];
$validator = validator($request->all(), $rules, $error_messages);
My form looks like the following:
<form id="Register" class="card-body" tabindex="500" action="{{ url('register') }}" method="POST">
<!-- CSRF Token -->
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<div class="name">
<input type="text" name="username" value="{!! old('username') !!}">
<label>Username</label>
<li>
{!! $errors->first('username.required', '<ul><span style="color: red;" class="help-block">:message</span></ul>') !!}
{!! $errors->first('username.min', '<ul><span style="color: red;" class="help-block">:message</span></ul>') !!}
{!! $errors->first('username.max', '<ul><span style="color: red;" class="help-block">:message</span></ul>') !!}
{!! $errors->first('username.alpha_dash', '<ul><span style="color: red;" class="help-block">:message</span></ul>') !!}
</li>
</div>
<div class="mail">
<input type="email" name="email" value="{{ old('email') }}">
<label>Mail</label>
{!! $errors->first('email.unique', '<span style="color: red;" class="help-block">:message</span>') !!}
{!! $errors->first('email.required', '<span style="color: red;" class="help-block">:message</span>') !!}
{!! $errors->first('email.email', '<span style="color: red;" class="help-block">:message</span>') !!}
</div>
<div class="passwd">
<input type="password" name="password" value="{{ old('password') }}">
<label>Password</label>
{!! $errors->first('password.min', '<span style="color: red;" class="help-block">:message</span>') !!}
{!! $errors->first('password.confirmed', '<span style="color: red;" class="help-block">:message</span>') !!}
{!! $errors->first('password.required', '<span style="color: red;" class="help-block">:message</span>') !!}
</div>
<div class="passwd">
<input type="password" name="password_confirmation" value="{{ old('password_confirmation') }}">
<label>Confirm Password</label>
{!! $errors->first('password.confirmed', '<span style="color: red;" class="help-block">:message</span>') !!}
</div>
<div class="submit">
<!-- <a class="btn ripple btn-primary btn-block" href="#">Register</a> -->
<input type="submit" class="btn ripple btn-primary btn-block" value="Register">
</div>
<p class="text-dark mb-0">Already have an account?Sign In</p>
</form>
When I enter a username with 3 characters and without a - and my password lengths do not match I get all validation errors back:
However, I would only like to get the errors back that really apply.
Any suggestions what I am doing wrong?
I appreciate your replies!
You are asking the blade file to display every error that you have created by name/key, rather than seeing what's inside the error bag.
Laravel automatically presents the errors that apply to your page, and limits the output to only those that apply. You don't need to catch them individually by name as you have with $errors->first('email.unique')... etc.
Take a look at the docs on how to display validation errors, it's pretty nifty. Basically check the error bag and if they are presented, display only those that are in the bag:
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
The $errors variable is available to you on any view within a route under the web middleware.

Cannot find errors returned by validate method

I am using the validate method to validate user input and when I post a form with errors, I get redirected to the previous page but the form is not repopulated and the errors are not showing. I have include a partial view for showing errors in the page with the form. The partial view is:
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors as $error)
<li> {{ $error }} </li>
#endforeach
</ul>
</div>
#endif
the action method in the controller is:
public function store(Request $request)
{
$request->validate([
'product_name' => 'required',
'age' => 'required',
'product_code' => 'required|alpha_num',
'price' => 'required|numeric',
]);
$product=new Product();
The view with the form is:
#section('content')
<div class="container">
#include('partials.errors')
<form action="/products/create" method="POST">
<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
#csrf
<div class="form-group">
<label>Product Name</label>
<input name="product_name" type="text" class="form-control">
</div>
<div class="form-group">
<label>Age</label>
<input name="age" type="text" class="form-control">
</div>
<div class="form-group">
<label>Gender</label>
<select class="form-control" name="gender">
<option>
Male
</option>
<option>
Female
</option>
Unisex
</option>
</select>
</div>
<div class="form-group">
<label>Product Code</label>
<input name="product_code" type="text" class="form-control">
</div>
<div class="form-group">
<label>Price</label>
<input name="price" type="text" class="form-control">
</div>
<div class="form-group">
<label>Product Category</label>
<select class="form-control" name="category_name">
#foreach ($product_categories as $product_category)
<option>{{ $product_category->category_name }}</option>
#endforeach
</select>
</div>
<div class="form-group">
<label>Brand</label>
<select class="form-control" name="brand_name">
#foreach ($brands as $brand)
<option>{{ $brand->brand_name }}</option>
#endforeach
</select>
</div>
<button class="btn btn-primary" type="submit">Create</button>
</form>
</div>
#endsection
when I post a failed form, I get redirected to the view with the form but the form is not repopulated with the input that I entered. additionally, the erros are not shown but just an empty red div. According to a book I read, if the data isn’t valid, the validate method throws a ValidationException and the exception will return a redirect to the previous page, together with all of the user input and the validation errors. I am new to laravel.
You should use old() method to keep repopulate entered value in input field like below
<input name="product_code" type="text" class="form-control" value="{{ old('product_code') }}">
To show validation error you have to add errors in each field for example like below
#error("product_code")
<div class="invalid-feedback">{{ $message }}</div>
#enderror
You can read more about old method here
https://laravel.com/docs/8.x/requests#retrieving-old-input
For validation error
https://laravel.com/docs/8.x/validation#the-at-error-directive
First, the CSRF token:
If you check the docs you'll see that you have 2 options how to add it:
#csrf
<!-- Equivalent to... -->
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
You are doing both, remove one of them.
Second, the old input:
You are missing the old input call. For example:
<input name="product_code" type="text" class="form-control" value="{{ old('product_code') }}">
Last, the errors:
You are doing it correctly.
If is still not working, check that your route is using the middleware web.

Laravel save related data in database

I want to save question_id in answer table using post form
I tried to use foreach or functions but i always got null data
Controller
public function store(Request $request, Survey $survey)
{
$request->validate([
'answer' => 'required',
]);
$survey->option_name = unserialize($survey->option_name);
$answers = new Answer([
'answer' => $request->get('answer'),
'commentaire' => $request->get('commentaire'),
'user_id' => auth()->id(),
'last_ip' => request()->ip(),
'question_id' => $survey->questions,
'survey_id' => $survey->id,
]);
$answers->save();
return redirect()->action('SurveyController#view_survey_answers', [$survey->id]);
}
answers table
question table's row :
id
survey_id
title
timestamp
I got always null data or i tried using where but i got errors like id index doesn't exists...
View :
{!! Form::open(array('action'=>array('AnswerController#store', $survey->id))) !!}
#forelse ($survey->questions as $key=>$question)
<p class="flow-text">Question {{ $key+1 }} - {{ $question->title }}</p>
#if($question->question_type === 'text')
<div class="form-group">
<div class="input-field col s12">
<input id="answer" type="text" name="answer">
<label for="answer">Answer</label>
</div>
</div>
#elseif($question->question_type === 'textarea')
<div class="form-group">
<div class="input-field col s12">
<textarea id="textarea1" class="materialize-textarea" name="{{ $question->id }}[answer]"></textarea>
<label for="textarea1">Textarea</label>
</div>
</div>
#elseif($question->question_type === 'radio')
#foreach($question->option_name as $key=>$value)
<p style="margin:0px; padding:0px;">
#if($value === 'else')
<div class="form-group" style="margin-left: 20px;">
<input name="answer" class="custom-control-input" type="radio" id="{{ $value }}" value="{{$value}}"/>
<label class="custom-control-label" for="{{ $value }}">{{ $value }}</label>
<div id="textboxes" style="display: none">
<br>
<textarea class="form-control" name="commentaire" id="exampleFormControlTextarea1" rows="3" placeholder="Write a large text here ..."></textarea>
</div>
</div>
#else
<p style="margin:0px; padding:0px;">
<div class="form-group" style="margin-left: 20px;">
<input name="answer" class="custom-control-input" type="radio" id="{{ $value }}" value="{{ $value}}"/>
<label class="custom-control-label" for="{{ $value }}">{{ $value }}</label>
</div>
</p>
#endif
#endforeach
#elseif($question->question_type === 'checkbox')
#foreach($question->option_name as $key=>$value)
<p style="margin:0px; padding:0px;">
<div class="form-group">
<input type="checkbox" id="{{ $value }}" name="answer" value="{{$value}}"/>
<label for="{{$value}}">{{ $value }}</label>
</div>
</p>
#endforeach
#endif
<div class="divider" style="margin:10px 10px;"></div>
#empty
<span class='flow-text center-align'>Nothing to show</span>
#endempty
<div class="form-group">
{{ Form::submit('Submit Survey', array('class'=>'btn btn-success mt-4')) }}
</div>
{!! Form::close() !!}

Editing user info using laravel

I've built a cms interface for the admin in my website. among other things the admin can add\edit users info using forms.
when I send the edit form I keep getting this error: Column not found: 1054 Unknown column 'updated_at' in 'field list' which suggests that the DB update is trying to save all of the request indexes (which contains values of columns from other table) and not just the one I'm trying to update.
I've manage to track the problem to one line $user_role->save();.
the lines above that do what their suppose to (finding thr correcct user_role and change its value).
Here is my code
Model
static public function update_user($request, $id){
$image_name = '';
if( !empty($request['profile_image']) && $request->hasFile('profile_image') && $request->file('profile_image')->isValid() ){
$file = $request->file('profile_image');
$image_name = date('Y.m.d.H.i.s') . '-' . $file->getClientOriginalName();
$request->file('profile_image')->move( public_path() . '/images/profile-images/' , $image_name);
$img = Image::make( public_path() . '/images/profile-images/' . $image_name );
$img->resize(370, null, function ($constraint) {
$constraint->aspectRatio();
});
$img->save();
}
$user = self::find($id);
$user->name = $request['name'];
$user->email = $request['email'];
$user->phone = $request['phone'];
if( !empty($request['password']) ){
$user->password = bcrypt($request['password']);
}
if(!empty($image_name)){
$user->profile_image = $image_name;
}
if( !empty($request['role_id']) ){
$user_role = Users_role::find($id);
$user_role->role_id = $request['role_id'];
$user_role->save();
}
$user->save();
Session::flash('sm', 'Your profile has been updated');
Session::flash('sm-position', 'toast-top-center');
Session::put('user_name', $request['name']);
}
View
<div class="row">
<div class="span9">
<div class="content">
<div class="module message">
<div class="module-head">
<h3><b>Edit Product</b></h3>
</div><br>
<div class="content">
<div class="module message">
<div class="module-body">
<form action="{{ url('cms/users/' . $user->id) }}" method="POST" novalidate="novalidate" autocomplete="off" enctype="multipart/form-data">
<div class="module-body">
#method('PUT')
#csrf
<input type="hidden" name="user_id" value="{{ $user->id}}">
<div class="form-group">
<div class="input-group mb-3">
<div class="w-100 field-input-cms">
<label for="category-id" class="input-group-text h-50"><span class="text-danger">*</span><b> Permissions:</b></label>
<select name="role_id" class="custom-select span-8">
<option #if ( $user->role_id == 8 ) selected="selected" #endif value="8">Admin</option>
<option #if ( $user->role_id == 2 ) selected="selected" #endif value="2">Regular</option>
</select>
</div>
<small class="text-muted help-text">Please select one option</small><br>
<span class="text-danger"> {{ $errors->first('category_id') }}</span>
</div>
<div class="w-100 field-input-cms">
<label for="name" class="input-group-text h-100"><span class="text-danger">*</span><b> Name:</b></label>
<input type="text" value="{{ $user->name }}" name="name" style="width:100%" class="form-control" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-default">
</div>
<small class="text-muted help-text">Name of user</small><br>
<span class="text-danger"> {{ $errors->first('name') }}</span>
<div class="field-input-cms w-100">
<label for="email" class="input-group-text"><span class="text-danger">*</span><b> Email:</b></label>
<input type="text" value="{{ $user->email }}" name="email" size="120" class="form-control mw-100" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-default">
</div>
<small class="text-muted text-balck help-text"> Email of user</small><br>
<span class="text-danger"> {{ $errors->first('email') }}</span>
<div class="field-input-cms w-100">
<label for="phone" class="input-group-text"><span class="text-danger">*</span><b> Phone:</b></label>
<input type="text" value="{{ $user->phone }}" name="phone" size="120" class="form-control mw-100" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-default">
</div>
<small class="text-muted text-balck help-text"> Phone number of user</small><br>
<span class="text-danger"> {{ $errors->first('phone') }}</span>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroupFileAddon01">Upload</span>
</div>
<div class="custom-file">
<input type="file" name="profile_image" class="custom-file-input" id="inputGroupFile01" aria-describedby="inputGroupFileAddon01">
<label class="custom-file-label" name="profile_image" for="inputGroupFile01">Choose file</label>
</div>
</div>
<small class="text-muted help-text">Image must be: jpg, jpeg, png, gif. Max: 5mb</small><br>
<span class="text-danger"> {{ $errors->first('profile_image') }}</span>
</div>
<div class="form-group">
<img id="cms-profile-image" src="{{ asset('images/' . $user->profile_image) }}" >
</div><br>
<a class="btn btn-inverse" href="{{ url('cms/users') }}">Cancel</a>
<input type="submit" value="Save Product" name="submit" class="btn btn-primary">
</div>
</form>
</div>
</div>
</div>
</div>
</div> <!--/.content-->
</div><!--/.span9-->
</div>
Image of the error gaven by laravel
I should mention that if I comment out this code:
if( !empty($request['role_id']) ){
$user_role = Users_role::find($id);
$user_role->role_id = $request['role_id'];
$user_role->update();
}
all the values are saved correctly.
If your users table doesn't have created_at and updated_at columns you should set:
public $timestamps = false;
in your User model.
Laravel by default assumes you have those fields for tables. So whenever record is created/updated it will automatically set/update those fields.
Alternatively you can update your table structure to add those fields and then those fields will be automatically handled by Laravel (in such case don't set timestamps to false).
You might be interested to read about Eloquent conventions

How to seperate validation error list in laravel

Code in blade
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
Name: <input type="text" name="name">
Phone: <input type="text" name="phone">
Email: <input type="text" name="email">
Validation Code
$data = $this->validate($request,[
'name' => 'required',
'phone' => 'required',
'email' => 'required',
]);
I wanna display each error under its input field.
You have to add error message after input field
<div class="form-group {{ $errors->has('name') ? 'has-error' : ''}}">
<label for="name" class="col-sm-3 control-label">Name: </label>
<div class="col-sm-7">
<input class="form-control" required="required" name="name" type="text" id="name">
{{ $errors->first('name', '<p class="help-block">:message</p>') }}
</div>
</div>
To display each error seperatly you can just use $errors->first() and pass in the field name you're requesting. See the following example.
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
Name: <input type="text" name="name">
{{ $errors->first('name') }}
Phone: <input type="text" name="phone">
{{ $errors->first('phone') }}
Email: <input type="text" name="email">
{{ $errors->first('email') }}
Notice after each field I call $errors->first()
Name: <input type="text" name="name">
<small class="text-danger">{{ $errors->first('name') }}</small>
Phone: <input type="text" name="phone">
<small class="text-danger">{{ $errors->first('phone') }}</small>
Email: <input type="text" name="email">
{{ $errors->first('email') }}
If condition is not needed if u don't want to show all errors at a place.
Also, two types the error message can be display
{{ $errors->first('name') }}
<small class="text-danger">{{ $errors->first('phone') }}</small>

Resources