Issue
I am making a blogging application with Laravel 8 and Bootstrap 5.
I run into a problem trying to validate my "Add new article" form: when the form fails validation, the valid fields do not keep their values, despite ne using Blade's old()
method.
In the controller, I have:
namespace App\Http\Controllers\Dashboard;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use App\Models\ArticleCategory;
use App\Models\Article;
use Illuminate\Http\Request;
class ArticleController extends Controller
{
private $rules = [
'category_id' => ['required', 'exists:article_categories,id'],
'title' => ['required', 'string', 'max:255'],
'short_description' => ['required', 'string', 'max:255'],
'image' => ['mimes: jpeg, jpg, png, gif', 'max:2048'],
'content' => ['required', 'string']
];
private $messages = [
'category_id.required' => 'Please pick a category for the article',
'title.required' => 'Please provide a title for the article',
'short_description.required' => 'The article needs a short description',
'content.required' => 'Please add content'
];
public function categories() {
return ArticleCategory::all();
}
public function index() {
$articles = Article::paginate(10);
return view('dashboard/articles',
['articles' => $articles]
);
}
public function create() {
// Load the view and populate the form with categories
return view('dashboard/add-article',
['categories' => $this->categories()]
);
}
public function save(Request $request) {
// Validate form (with custom messages)
$validator = Validator::make($request->all(), $this->rules, $this->messages);
if ($validator->fails()) {
return redirect()->back()->withErrors($validator->errors());
}
$fields = $validator->validated();
// Upload article image
$current_user = Auth::user();
if (isset($request->image)) {
$imageName = md5(time()) . $current_user->id . '.' . $request->image->extension();
$request->image->move(public_path('images/articles'), $imageName);
}
// Data to be added
$form_data = [
'user_id' => Auth::user()->id,
'category_id' => $fields['category_id'],
'title' => $fields['title'],
'slug' => Str::slug($fields['title'], '-'),
'short_description' => $fields['short_description'],
'content' => $fields['content'],
'image' => $fields['image'],
'featured' => $fields['featured']
];
// Insert data in the 'articles' table
$query = Article::create($form_data);
if ($query) {
return redirect()->route('dashboard.articles')->with('success', 'Article added');
} else {
return redirect()->back()->with('error', 'Adding article failed');
}
}
}
The form:
<form method="POST" action="{{ route('dashboard.articles.add') }}">
@csrf
<div class="row mb-2">
<label for="title" class="col-md-12">{{ __('Title') }}</label>
<div class="col-md-12 @error('title') has-error @enderror">
<input id="title" type="text" placeholder="Title" class="form-control @error('title') is-invalid @enderror" name="title" value="{{ old('title') }}" autocomplete="title" autofocus>
@error('title')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-2">
<label for="short_description" class="col-md-12">{{ __('Short description') }}</label>
<div class="col-md-12 @error('short_description') has-error @enderror">
<input id="short_description" type="text" placeholder="Short description" class="form-control @error('short_description') is-invalid @enderror" name="short_description" value="{{ old('short_description') }}" autocomplete="short_description" autofocus>
@error('short_description')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-2">
<label for="category" class="col-md-12">{{ __('Category') }}</label>
<div class="col-md-12 @error('category_id') has-error @enderror">
<select name="category_id" id="category" class="form-control @error('category_id') is-invalid @enderror">
<option value="0">Pick a category</option>
@foreach($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
@endforeach
</select>
@error('category_id')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-2">
<div class="col-md-12 d-flex align-items-center switch-toggle">
<p class="mb-0 me-3">Featured article?</p>
<input class="mt-1" type="checkbox" name="featured" id="featured">
<label class="px-1" for="featured">{{ __('Toggle') }}</label>
</div>
</div>
<div class="row mb-2">
<label for="image" class="col-md-12">{{ __('Article image') }}</label>
<div class="col-md-12 @error('image') has-error @enderror">
<input type="file" name="image" id="file" class="file-upload-btn">
@error('image')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-2">
<label for="content" class="col-md-12">{{ __('Content') }}</label>
<div class="col-md-12 @error('content') has-error @enderror">
<textarea name="content" id="content" class="form-control @error('content') is-invalid @enderror" placeholder="Content" cols="30" rows="6">{{ old('content') }}</textarea>
@error('content')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-0">
<div class="col-md-12">
<button type="submit" class="w-100 btn btn-primary">
{{ __('Save') }}
</button>
</div>
</div>
</form>
The routes:
// Article routes
Route::group(['prefix' => 'articles'], function() {
Route::get('/', [ArticleController::class, 'index'])->name('dashboard.articles');
Route::get('/new', [ArticleController::class, 'create'])->name('dashboard.articles.new');
Route::post('/add', [ArticleController::class, 'save'])->name('dashboard.articles.add');
Route::get('/delete/{id}', [ArticleController::class, 'delete'])->name('dashboard.articles.delete');
});
The problem:
I was expecting this syntax for keeping the values of valid fields in an invalid form, should work: value="{{ old('title') }}"
. But, fo a reason I have been enable to spot, it does not. The form is reset entirely.
What is my mistake?
Solution
You're redirecting back to the previous page without telling Laravel to pass the old inputs. Use the method withInput()
with the route return.
Change
return redirect()->back()->withErrors($validator->errors());
with
return redirect()->back()->withErrors($validator->errors())->withInput();
Answered By - OMi Shah Answer Checked By - David Goodson (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.