Create multiple form groups with multiple fields in Laravel and jQuery

If I have for example a group session or a course class, and I want to add all attendees, I need to provide a solution to add all my attendees without knowing how many will be there, It could be 1 or 10 you’ll never know.

So we just append some fields, as we want with jQuery, and and add them to a specific table on the database.

Like this could be the final product then.

Let’s start with the frontend.

The Frontend

Using Boostrap, I’ll made a form with some different fields for the group session, and also included a group Session photo. For the non repeatable fields I chose: the session photo, Host, Session Date, Type, And for the repeatable fields, just a button for now, because we will add the fields with jQuery.

[alert style=”warning”]Keep in mind that, all uppercase words indicate that you need to adjust it with your project. Except the form method[/alert]

<form id="THEFORM" action="{!! action('THECONTROLLER@store') !!}" method="POST" enctype="multipart/form-data">
    {{ csrf_field() }}

    <div class="row">
        <section class="main-data row">
            <div class="col-md-5 fillerr">
                <div class="form-group">
                    Group photo

                    <br>
                    <input class="add-img" type="file" name="file" onchange="readURL(this);" accept="image/x-png,image/gif,image/jpeg">
                    <br>
                </div>
            </div>
            <div class="col-md-7">
                <div class="form-group">
                     Host
                    <input name="host" type="text" class="form-control" id="host" />
                </div>
                <div class="form-group">
                    Session Date 
                    <input name="date" type="text" class="form-control id="sessiondate" />
                </div>
                <div class="form-group">
                    Type
                    <select class="form-control" name="type" title="" required>
                        <option value=""></option>
                        <option value="FIRST">FIRST</option>
                        <option value="SECOND">SECOND</option>
                        <option value="THIRD">THIRD</option>
                        <option value="FOURTH">FOURTH</option>
                    </select>
                </div>
            </div>
        </section>
        
        <section class="add-people row">
            <h4>Add Session Attendees</h4>
            <div class="people-container">
                <button class="add-new btn btn-success" type="button"><i class="fa fa-plus"></i>Add new Attendee</button>
            </div>
        </section>
    </div>

    <hr>
    <input class="btn btn-success pull-right" type="submit"  />
</form>

The Javascript

The js, adds some fields, to the add-people section, so for this I just needed 3 simple fields, the name, surname, and birthday, of course you can add more.

Simply enough we wait for the document to load, add some Variables, such as how much fields, is the maximum, indication the wrapper, and which button are we using to add the fields, in this case it’s wrapper, as people-container, and the button is add-new, all referring to classes. I also added a x variable with the default value 0, so I know how many fields, are there this can be used for validation as well. the I targeted the button and added a click event to it. by preventing the default I don’t allow the button to submit the form. and looked up if there are any fields, with the if function. added one to the x variable, and appended the complete html to the wrapper. because I had a data field there and I wanted to use the jQuery date picker I left a date-picker Method in there for every fields that is creased. as well in there. at last on the else class I added a simple alert to tell that the limit is reached.  and provided the code to remove a field.

$(document).ready(function() {
    var max_fields      = 50;
    var wrapper         = $(".people-container");
    var add_button      = $(".add-new");
    var x = 0;

    $(add_button).click(function(e){
        e.preventDefault();
        if(x < max_fields){
            x++;
            $(wrapper).append(
                '<div class="filedset attendee">' +
                    '<div class="col-md-3 col-md-offset-1">' +
                        '<div class="form-group">Name<input type="text" class="form-control" name="sessionAttende[' + x + '][name]" title="" autocomplete="given-name" ></div>' +
                    '</div>' +
                    '<div class="col-md-3">' +
                        '<div class="form-group">Surname<input type="text" class="form-control" name="sessionAttende[' + x + '][surname]" title="" autocomplete="given-name" ></div>' +
                    '</div>' +
                    '<div class="col-md-3">' +
                        '<div class="form-group">Birthday<input name="sessionAttende[' + x + '][birthday]" type="text" class="form-control datepicker-field" id="dateField' + x + '" /></div>' +
                    '</div>' +
                    '<br><button class="delete btn btn-danger" type="button"><i class="fa fa-minus"></i></button>' +
                '</div>'); //add input box

             $(".datepicker-field").datepicker({
                changeYear: true,
                dateFormat: "dd-mm-yy",
                yearRange: "-100:+0",
                maxDate : "0",
            });
        }
else
{
alert('You Reached the limits')
}
    });
    $(wrapper).on("click",".delete", function(e){
        e.preventDefault(); $(this).parent('div').remove(); x--;
    })
});

The Controller

Now comes the interesting part.  so because for this I use Laravel 5.6 I am able to use some cool stuff, for now.

So I just request all fields with the $request->all() method, to the create() methode, and used the GroupSession facade for the model.  for the file aka the Session Image, I used the MediaUploader but you can use normal Laravel for this as well, of course.

and for the repeatable fields, added the createMany() methode to the SessionAttendee model, and requested all sessionAttende fields.

at last redirected to a view, and good is.

use IlluminateHttpRequest;
use AppGroupSession;
use MediaUploader;
use AppSessionAttendee;

public function store(Request $request)
{
    $groupSession = GroupSession::create($request->all());

    if($request->hasFile('file')){
        $media = MediaUploader::fromSource($request->file('file'))
            ->toDestination('local', "media/group_session")
            ->upload();
            
        $groupSession->attachMedia($media, 'groupsession');
    }

    $groupSession->sessionAttendee()->createMany($request->input('sessionAttende'));

    return redirect('groupsession');
}

The Models

For this I needed 2 models, and used a many-to-one relationship for the non-repeatable and repeatable fields.

The GroupSession

In this Model I added a protected fillable, for the non-repeatable fields, and build the relationship with SessionAttendee model,

use IlluminateDatabaseEloquentModel;
use PlankMediableMediable;
use CarbonCarbon;
use SpatieActivitylogTraitsLogsActivity;

class GroupSession extends Model
{
    use Mediable, LogsActivity;
    
    protected $fillable = [
        'host',
        'date',
        'behavior',
        'type',
    ];

    // one to many with session attendees
    public function sessionAttendee()
    {
        return $this->hasMany(SessionAttendee::class);
    }
}

The SessionAttendee Model

In this Model, I needed to use the belongsTo() method to connect it with GroupSession

use IlluminateDatabaseEloquentModel;
use CarbonCarbon;
use SpatieActivitylogTraitsLogsActivity;

class SessionAttendee extends Model
{
    use LogsActivity;

    protected $table = 'session_attendiees';

    protected $fillable = ['name', 'surname', 'birthday'];

    public function groupSession()
    {
        return $this->belongsTo(GroupSession::class);
    }

    public function setBirthdayAttribute($value)
    {
        $this->attributes['birthday'] = new Carbon($value);
    }
}

The Migrations

The Session Table, Migration contains these fields,

public function up()
{
    Schema::create('group_sessions', function (Blueprint $table) {
        $table->increments('id');
        $table->string('photo');
        $table->string('host');
        $table->dateTime('date');
        $table->string('behavior');
        $table->string('type');
        $table->timestamps();

    });
}

and the other one:

Schema::create('session_attendiees', function (Blueprint $table) {
    $table->increments('id');
    $table->unsignedInteger('group_session_id');
    $table->string('name');
    $table->string('surname');
    $table->date('birthday');
    $table->timestamps();

});

So as you can see the first one is the non-repeatable and the second one repeatable. and it's the same as the fields.

Tech Versions.

  • Laravel 5.6
  • Jquery 2.x
CategoriesUncategorized

3 Replies to “Create multiple form groups with multiple fields in Laravel and jQuery”

  1. After reading your post, you have a great website with interesting content. But I think you can improve your current google ranks by using this service. My friend uses it and it works great. Just check to https://bitly.com/2NXGS6L, it’s very nice tool to bring you a lot of new readers on a daily basis. Keep up the quality work!

Leave a Reply

Your email address will not be published.