Jakub Kohout
Jakub Kohout

Reputation: 1944

Laravel 5 dynamic form validatioin

I have a form which has fields that can be added dynamicly. Everything works fine, but when I add some fields and submit and I make some mistake on purpose and validation fails, the dynamicly created fields disappear.

Let's say that I have 3 static fields and one dinamicly added. so it looks like that

static fields: keyword1, keyword2, keyword3

dynamic fields: keyword4

The validation error message that I get is like this:

The keyword0 field is required.
The keyword1 field is required.
The keyword2 field is required.
The keyword3 field is required.

fields 0,1,2 are in the the form with the values that I filled for them, but field 3 is not that.

How can I access this field so I can print it in my form?

my form

{!! Form::model($keywordsPlan, ['route' => ['keywordsplans.store', 'company' => $company], 'method' => 'POST', 'class' => 'form-horizontal keywords-plan-form']) !!}


<div class="row">               
    <div class="col-md-4 col-md-offset-4" style="margin-bottom: 20px;">
        {!! Form::label('Date') !!}
        {!! Form::date('date', null, ['class' => 'form-control']) !!}
    </div>


    <table class="table table-stripped">
        <thead>
            <tr>
                <th>Add Keyword</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td scope="row">{!! Form::text(null, null, ['class' => 'form-control keyword-input']) !!}</td>
                <td scope="row"><a href="#" class="btn btn-primary add-keyword">Add keyword</a></td>
            </tr>
        </tbody>
    </table>

    <table class="table table-striped keywords-table">
        <thead>
            <tr>
                <th>Keyword</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            @foreach ($keywords as $i => $keyword)
            <tr class="keyword-row">
                <td scope="row">{!! Form::text('keyword['.$i.']', $keyword->text, ['class' => 'form-control']) !!}</td>
                <td class="action"><input type="button" class="btn btn-danger remove-keyword" value="Remove"></td>
            </tr>
            @endforeach
            <tr class="keyword-copy-row hidden">
                <td>{!! Form::text(null, null, ['class' => 'form-control']) !!}</td>
                <td class="action"><input type="button" class="btn btn-danger remove-keyword" value="Remove"></td>
            </tr>
        </tbody>
    </table>

    <div class="col-md-4 col-md-offset-4 text-center">
        {!! Form::submit('Create Plan', ['class' => 'btn btn-success btn-lg save-plan']); !!}
    </div>
</div>


{!! Form::close() !!}

and this is my Request class for this model (form)

 /**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public function rules()
{


    $rules = [
        'date' => 'required|date|unique:keywords_plans,date',
        'approved' => 'boolean'
    ];

    for ($i = 0; $i < count($this->keyword); $i++) {

        $rules['keyword'.$i] = 'required';

    }

    return $rules;

}

My controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Keyword;
use App\Company;
use App\Http\Controllers\Controller;

use App\KeywordsPlan;
use App\Http\Requests\CreateKeywordsPlan;
use App\Http\Requests\UpdateKeywordsPlan;

class KeywordsPlanController extends Controller
{


    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        $keywordsPlans = KeywordsPlan::all();
        return view('keywordsPlans/index', compact('keywordsPlans'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return Response
     */
    public function create($company)
    {
        $data['keywordsPlan'] = new KeywordsPlan;
        $data['company'] = Company::find($company);
        $data['keywords'] = $data['company']->keywords;

        return view("keywordsPlans/create", $data);
    }
}

Upvotes: 0

Views: 1415

Answers (2)

user2754876
user2754876

Reputation: 40

There are a few mistakes in Ur code at the moment.

1) The rules.

It needs to be

$rules['keyword.'.$i] = 'required';

Ur currently checking for 'keyword0'. U need to be checking for 'keyword.0'. U need a extra '.'.

Laravel's validatior uses array.index when it needs to check array['index']'s value.

U can actually just add 'keyword.*' = 'required' into the rules array instead of the for loop there. (Available in 5.2. Not sure about previous versions.)

2) When Ur repopulating the form after errors U need to be repopulating using values from session. But Ur using $keywords regardless of wether its a fresh form or a repopulated one.

U need to do something like this

  @if (Input::old('keywords'))
        @foreach (Input::old('keywords') as $i => $keyword)
         <tr class="keyword-row">
                <td scope="row">{!! Form::text('keyword['.$i.']', $keyword->text, ['class' => 'form-control']) !!}</td>
                <td class="action"><input type="button" class="btn btn-danger remove-keyword" value="Remove"></td>
            </tr>
        @endforeach
@else
         @foreach ($keywords as $i => $keyword)
            <tr class="keyword-row">
                <td scope="row">{!! Form::text('keyword['.$i.']', $keyword->text, ['class' => 'form-control']) !!}</td>
                <td class="action"><input type="button" class="btn btn-danger remove-keyword" value="Remove"></td>
            </tr>
            @endforeach

    @endif

And also for non-dynamic form values U will need to use the old helper this way.

{!! Form::date('date', Input::old('date'), $date, ['class' => 'form-control']) !!}

Check these links to know more about this stuff. https://laravelcollective.com/docs/5.2/html#form-model-binding. Note the priority order

Upvotes: 1

djt
djt

Reputation: 7535

From what I can see, it seems like your validations IS working. If you receive the following errors:

The keyword0 field is required.
The keyword1 field is required.
The keyword2 field is required.
The keyword3 field is required.

This line:

for ($i = 0; $i < count($this->keyword); $i++) {

Is looping through items 0 through 3, which is a total of 4 items. You said you have 3 static items plus 1 dynamic. Is that not accurate?

Upvotes: 0

Related Questions