问题
The new @error directive was introduced in Laravel 5.8.13. So, instead of doing this:
// old
@if ($errors->has('email'))
<span>{{ $errors->first('email') }}</span>
@endif
You can now do this
// new
@error('email')
<span>{{ $message }}</span>
@enderror
However, I'm having issues trying to target only the input fields where the error was made among several similar input fields. These fields are similar because they have the same name. But they are also in seperate forms and have different submit buttons.
My html blade file is setup with multiple inputs generated from a @forelse
statement. I've created a simple error check to check if a negative number is entered and to redirect back to the same page with an error message. The @error
directive is also used to insert a custom class to target input field for styling.
@forelse($accounts as $account)
<form method="POST" action="{{ route('account.update', $account->id) }}">
@csrf
<div>
<input type="number" name="credit" class="@error('credit') is-invalid @enderror" required>
<input type="submit" class="btn" value="ok">
@error('credit')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</form>
@empty
@endforelse
The form submits to the update()
method in AccountController.php
public function update(Request $request, Account $account)
{
if($request->input('credit') < 0)
{
return back()->withErrors(['credit'=>'enter a positive amount']);
}
// ... other logic
}
The problem is that when a negative number is entered in one input field, the error message shows up for every input with the same name, even when they are not in the same form.
I think making the input names unique will solve this, but this will make my backend logic more complex than is required.
Is there anyway of making the error message show for just the target input after the redirect, without having to use unique names for each input field?
回答1:
A solution would be doing the following:
- store the value / posted form in a variable using the value of the submit button
- ditch the error directive and use the old version
- combine the old version with the variable to check wether you have the correct form or not
You'll get something like this:
@if ($errors->has('email') && $submitted_form_identifier === $form_identifier)
<span>{{ $errors->first('email') }}</span>
@endif
回答2:
Interestingly, the @error
directive is not programmatically tied to any input field by an input name. It is only spatially related to an input field by proximity and can be placed any where on the page.
Also, you can conveniently use any string within the @error
directive as long as same is passed to the withErrors()
call in the controller.
So, solving the problem of targeting the appropriate input among multiple ones becomes as simple as using any unique string (not necessarily the target input name) as key in the withErrors()
method call and retrieving the error message by passing the same string to the @error
directive. In my case, I chose to use the account id as the unique string.
In AccountController.php
:
public function update(Request $request, Account $account)
{
if($request->input('credit') < 0)
{
return back()->withErrors([$account->id=>'enter a positive amount']);
}
// ... other logic
}
And in the html blade template:
@forelse($accounts as $account)
<form method="POST" action="{{ route('account.update', $account->id) }}">
@csrf
<div>
<input type="number" name="credit" class="@error($account->id) is-invalid @enderror" required>
<input type="submit" class="btn" value="ok">
@error($account->id)
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</form>
@empty
@endforelse
NOTE: Using a non existent key in any @error
directive breaks the code for other @error directives and will cause no error messages to be displayed.
来源:https://stackoverflow.com/questions/57987121/using-error-directive-to-target-the-previous-input-field-from-multiple-input-fi