'laravel - Display validation error in the proper tab
I am using the bootstrap tab to navigate between three different tabs for a user. First tab(primary tab) is to display user details and second tab is to edit the information and the third tab allows user to change the password.
Whenever I made a validation error, say in the edit tab, then it will return to the first tab and I'll have to select the edit tab to see the error. Similarly, any validation error from the third tab will also return to my first tab.
show.blade.php:
div class="container">
<div class="row my-2">
<div class="col-lg-8 order-lg-2">
<ul class="nav nav-tabs">
<li class="nav-item">
<a href="" data-target="#profile" data-toggle="tab" class="nav-link active">Profile</a>
</li>
@can('update',$user)
<li class="nav-item">
<a href="" data-target="#edit" data-toggle="tab" class="nav-link">Edit</a>
</li>
@endcan
<li class="nav-item">
<a href="" data-target="#change-password" data-toggle="tab" class="nav-link">Change Password</a>
</li>
</ul>
<div class="tab-content py-4">
<div class="tab-pane active" id="profile">
<h5 class="mb-3">User Profile</h5>
<div class="row">
<div class="col-md-6">
<h6>Name</h6>
<p>
{{$user->name}}
</p>
<h6>Email</h6>
<p>
{{$user->email}}
</p>
</div>
</div>
<!--/row-->
</div>
<div class="tab-pane " id="edit">
<form method="POST" action="{{route('profile.update',[$user])}}">
@csrf
@method('PATCH')
<div class="form-group row">
<label class="col-lg-3 col-form-label form-control-label">Name</label>
<div class="col-lg-9">
<input class="form-control" type="text" id="name" name="name" onkeyup="checkInput()" value="{{$user->name}}" >
</div>
</div>
<div class="form-group row">
<label class="col-lg-3 col-form-label form-control-label">Email</label>
<div class="col-lg-9">
<input class="form-control" type="email" name="email" value="{{$user->email}}" disabled>
</div>
</div>
<div class="form-group row">
<label class="col-lg-3 col-form-label form-control-label"></label>
<div class="col-lg-9">
<input type="reset" class="btn btn-secondary" value="Cancel">
<button type="submit" id="save-btn" class="btn btn-primary" disabled>Save Changes</button>
</div>
</div>
@if(count($errors))
<ul class="alert alert-danger">
@foreach($errors->all() as $error)
<li>{{$error}}</li>
@endforeach
</ul>
@endif
</form>
</div>
<div class="card tab-pane " id="change-password">
<div class="card-header">Change password</div>
<div class="card-body">
@if (session('error'))
<div class="alert alert-danger">
{{ session('error') }}
</div>
@endif
@if (session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<form class="form-horizontal" method="POST" action="{{route('changePassword')}}">
@csrf
<div class="form-group{{ $errors->has('current-password') ? ' has-error' : '' }}">
<label for="new-password" class="col-md-4 control-label">Current Password</label>
<div class="col-md-6">
<input id="current-password" type="password" class="form-control" name="current-password" required>
@if ($errors->has('current-password'))
<span class="help-block">
<strong>{{ $errors->first('current-password') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group{{ $errors->has('new-password') ? ' has-error' : '' }}">
<label for="new-password" class="col-md-4 control-label">New Password</label>
<div class="col-md-6">
<input id="new-password" type="password" class="form-control" name="new-password" required>
@if ($errors->has('new-password'))
<span class="help-block">
<strong>{{ $errors->first('new-password') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group">
<label for="new-password-confirm" class="col-md-4 control-label">Confirm New Password</label>
<div class="col-md-6">
<input id="new-password-confirm" type="password" class="form-control" name="new-password_confirmation" required>
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary">
Change Password
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
ProfileController:
public function update(UpdateProfileRequest $request, User $user){
$this->authorize('update',$user);
$validated = $request->validated();
$user->update([
'name' => $request->input('name')
]);
return redirect($user->path())->with('message',"Profile has been updated");;
}
ChangePasswordController:
public function changePassword(Request $request){
if (!(Hash::check($request->input('current-password'), Auth::user()->password))) {
// The passwords matches the password of the user in the database
return redirect()->back()->with("error","Your current password does not matches with the password you provided. Please try again.");
}
if(strcmp($request->get('current-password'), $request->get('new-password')) == 0){
//Current password and new password are same
return redirect()->back()->with("error","New Password cannot be same as your current password. Please choose a different password.");
}
$validatedData = $request->validate([
'current-password' => 'required',
'new-password' => 'required|string|min:8|confirmed',
]);
//Change Password
$user = Auth::user();
$user->password = bcrypt($request->input('new-password'));
$user->save();
return redirect()->back()->with("success","Password changed successfully !");
}
I tried adding :
...
<div class="tab-pane {{ count($errors) ? '' : 'active' }}" id="profile">
...
<div class="tab-pane {{ count($errors) ? 'active' : '' }}" id="edit">
...
but it only works if there are two tabs. How can I tackle this?
Solution 1:[1]
You can activate tabs with specific field errors checking. This approach works because you also separated forms. There will be no errors in separated forms at the same time.
...
<div class="tab-pane {{ ($errors->has('name') || $errors->has('email')) ? 'active' : '' }}" id="profile">
...
<div class="tab-pane {{ ($errors->has('current-password') || $errors->has('new-password') || $errors->has('new-password_confirmation') ) ? 'active' : '' }}" id="edit">
...
Solution 2:[2]
Use the hidden field in your form like below.
<input type="hidden" name="tab" value="settings">
Then in your controller redirect like below.
$tab = $request->get('tab');
if($validator->fails()) {
return back()->withInput(['tab'=>$tab])->withError($validator->messages()->first());
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Enver Arslan |
Solution 2 | Siva R |