我如何验证文本框相互依赖,并动态(使用JS)添加输入文本框下显示错误消息?



在我的表格中,我参加了一个"研讨会"。文本输入集—用户输入研讨会标题、日期和研讨会指挥/组织者。

<table class="table" id="addRemoveSeminar">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Date Taken</th>
<th scope="col">Conducted By</th>
<th><button type="button" name="add" onclick="addSeminar()" id="dynamic-ar-seminar" class="btn btn-outline-primary">Add Seminar</button></th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row"><input type="text" id="" name="Seminars[0][title]"></th>
<td><input type="date" id="" name="Seminars[0][date]"></td>
<td><input type="text" id="" name="Seminars[0][conducted_by]"></td>
</tr>
</tbody>
</table>

表单最初只加载一组这些文本输入,但如果用户想要添加更多的研讨会,他们可以单击"添加Seminar"按钮,将出现这三个输入框的新集合。下面是js代码:

JS文件:

function addSeminar() {
var i = 0;
++i;
$("#addRemoveSeminar").append('<tr><th scope="row"><input type="text" id="" name="Seminars[' + i +
'][title]"></th><td><input type="date" id="" name="Seminars[' + i +
'][date]"></td><td><input type="text" id="" name="Seminars[' + i +
'][conducted_by]"></td><td><button type="button" class="btn btn-outline-danger remove-input-field">Delete</button></td></tr>'
);
$(document).on('click', '.remove-input-field', function () {
$(this).parents('tr').remove();
});
}

可以看到,titledateconducted_by的name属性将作为键添加到Seminars数组中。

问题1:如果验证失败,我不仅希望对所有错误调用foreach()并将它们显示在页面的顶部,还希望每个错误都显示在其对应的文本框的底部。即使是那些通过Javascript动态添加的。我怎么做呢?

问题2:目前,所有这些输入在验证规则中都是可空的。但是,如果用户应该在其中一个输入框中输入值,我希望其他两个输入框也是必需的。例如,如果用户键入研讨会标题,他不能将日期和传导值输入框保留为空。

我试着阅读Laravel文档:https://laravel.com/docs/8.x/validation#complex-conditional-validation部分,但我是努力弄清楚如何实现给定的示例

use IlluminateSupportFacadesValidator;
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'games' => 'required|numeric',
]);

,因为我对所有输入使用的当前验证语法是request()->validate()。我该怎么做呢?

我在控制器中的当前验证:

$validated = request()->validate([
'Seminars.*.title' => ['nullable','max:100',new LetterSpaceOnly],
'Seminars.*.date' => ['nullable','before_or_equal: today','date'],
'Seminars.*.conducted_by' =>  ['nullable','max:100',new LetterSpaceOnly]
]);

提前谢谢你

对于第二个问题,您可以首先使用required_with验证规则。您可以在文档

中查看。现在,对于第二个问题,因为字段是在DOM加载之后添加的,所以当Laravel验证输入时,它不会出现。
然而,这里有一个工作。
在这个例子中,我们可以使用old帮助器,你也可以在文档中检查它
这里有一点关于old的上下文,当你提交表单时,你所有的输入将被闪现到会话中,我们可以使用上面的帮助器检索它们。这里的变通方法是,当验证失败时,它会带着"旧的"输入返回,使用那个助手,我们可以重新创建第一个表,用户提交,我们可以在每个输入字段下显示错误。现在的代码:下面是视图的代码,我们在这里检查会话中是否有旧值:

<table class="table" id="addRemoveSeminar">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Date Taken</th>
<th scope="col">Conducted By</th>
<th><button type="button" name="add" onclick="addSeminar()" id="dynamic-ar-seminar" class="btn btn-outline-primary">Add Seminar</button></th>
</tr>
</thead>
<tbody>
@if (old('Seminars'))
@foreach (old('Seminars') as $key => $seminar)
<tr>
<th scope="row">
<input type="text" id="" name="Seminars[{{ $key }}][title]" value="{{ $seminar['title'] }}">
@if ($errors->has('Seminars.' . $key . '.title'))
{{ $errors->first('Seminars.' . $key . '.title') }}
@endif
</th>
<td>
<input type="date" id="" name="Seminars[{{ $key }}][date]" value="{{ $seminar['date'] }}">
@if ($errors->has('Seminars.' . $key . '.date'))
{{ $errors->first('Seminars.' . $key . '.date') }}
@endif
</td>
<td>
<input type="text" id="" name="Seminars[{{ $key }}][conducted_by]" value="{{ $seminar['conducted_by'] }}">
@if ($errors->has('Seminars.' . $key . '.conducted_by'))
{{ $errors->first('Seminars.' . $key . '.conducted_by') }}
@endif
</td>
<td><button type="button" class="btn btn-outline-danger remove-input-field">Delete</button></td>
</tr>
@endforeach
@else
<tr>
<th scope="row">
<input type="text" id="" name="Seminars[0][title]">
</th>
<td>
<input type="date" id="" name="Seminars[0][date]">
</td>
<td>
<input type="text" id="" name="Seminars[0][conducted_by]">
</td>
</tr>
@endif
</tbody>
</table>

这是控制器验证规则

$this->validate($request, [
'Seminars.*.title' => 'sometimes|required_with:Seminars.*.date, Seminars.*.conducted_by',
'Seminars.*.date' => 'sometimes|required_with:Seminars.*.title, Seminars.*.conducted_by',
'Seminars.*.conducted_by' => 'sometimes|required_with:Seminars.*.title, Seminars.*.date',
]);
...

另外,还有一件事,在你的JS代码中,onclick事件应该在函数之外。

function addSeminar() {
@if (old('Seminars'))
var i = {{ count(old('Seminars')) }} - 1;
@else
i= 0;
@endif
++i;
$("#addRemoveSeminar").append('<tr><th scope="row"><input type="text" id="" name="Seminars[' + i +
'][title]"></th><td><input type="date" id="" name="Seminars[' + i +
'][date]"></td><td><input type="text" id="" name="Seminars[' + i +
'][conducted_by]"></td><td><button type="button" class="btn btn-outline-danger remove-input-field">Delete</button></td></tr>'
);

}
$(document).on('click', '.remove-input-field', function () {
$(this).parents('tr').remove();
});

要更改验证消息,您可以这样使用它:

$this->validate($request, [
'Seminars.*.title' => 'sometimes|required_with:Seminars.*.date, Seminars.*.conducted_by',
'Seminars.*.date' => 'sometimes|required_with:Seminars.*.title, Seminars.*.conducted_by',
'Seminars.*.conducted_by' => 'sometimes|required_with:Seminars.*.title, Seminars.*.date',
],
[
'Seminars.*.title.required_with' => 'Custom message here',
'Seminars.*.date.required_with' => 'Custom message here',
'Seminars.*.conducted_by' => 'Custom message here',
]);

并根据需要更改消息。

我希望一切都清楚了。