Laravel表单:jQuery隐藏字段触发验证阻止提交问题求解
Hey there! Let's sort out this Laravel validation problem you're having with your dynamic ad submission form. The issue is clear: your backend is enforcing both titre and name as required, but users only fill one depending on the selected category. Here's how to fix it properly:
1. Core Fix: Conditional Validation in Laravel
The most important step is to update your validation rules so they only require the field that matches the selected category_id. Laravel has built-in rules for exactly this scenario:
Updated Controller Code (AdsController.php)
public function store(Request $request) { // First, validate the category selection to ensure it's valid $validated = $this->validate($request, [ 'category_id' => ['required', 'in:1,2'], 'titre' => ['bail', 'required_if:category_id,1', 'string', 'min:3', 'max:255'], 'name' => ['bail', 'required_if:category_id,2', 'string', 'min:3', 'max:255'], ]); // Instead of using $request->all(), only assign the necessary fields to avoid empty values $ads = new Ads(); $ads->category_id = $request->category_id; if ($request->category_id == 1) { $ads->titre = $request->titre; } else { $ads->name = $request->name; } $ads->save(); return Redirect::to("/")->withSuccess('Great! Ad has been successfully submitted.'); }
How This Works:
required_if:category_id,1tells Laravel: "only requiretitreifcategory_idis equal to 1"- Similarly,
required_if:category_id,2applies toname - We first validate
category_idto make sure it's either 1 or 2, which prevents invalid selections from breaking the logic
2. Optional Frontend Optimization
While backend validation is mandatory (since frontend can be bypassed), you can clean up the submitted data by removing the name attribute from hidden fields. This way, empty fields won't even be sent to the server:
Updated jQuery Code
<script> $(document).on('change', '#category_id', function() { var categoryId = $(this).val(); if (categoryId === '1') { // Hide name field and remove its name attribute $("#divn").hide().find('input').attr('name', ''); // Show titre field and restore its name attribute $("#divt").show().find('input').attr('name', 'titre'); } else if (categoryId === '2') { // Hide titre field and remove its name attribute $("#divt").hide().find('input').attr('name', ''); // Show name field and restore its name attribute $("#divn").show().find('input').attr('name', 'name'); } else { // If default "select" is chosen, hide both and clear names $("#divt, #divn").hide().find('input').attr('name', ''); } }); // Initialize the form state when the page loads $(document).ready(function() { $('#category_id').trigger('change'); }); </script>
Why This Helps:
- It prevents empty
titreornamevalues from being sent in the request - Makes your request data cleaner and avoids unnecessary fields in the payload
3. Bonus: Database Considerations
Make sure your ads database table allows titre and name to be nullable (unless you have a default value). If you're using migrations, your schema might look like this:
Schema::create('ads', function (Blueprint $table) { $table->id(); $table->integer('category_id'); $table->string('titre')->nullable(); $table->string('name')->nullable(); // Other fields... $table->timestamps(); });
This ensures that when you save an ad with only titre or name, the empty field won't cause a database error.
内容的提问来源于stack exchange,提问作者youssef jabboury

