Handling Form with model which has related models added dynamically via javascript
Since the ancient times this subject was equal for me with belzebub. The problem is as follows:
- Let's assume we've got some model like CoachingClass which describes school class.
- Create another model Student and create relation with CoachingClass of OneToMany.
- Now let's seed data of student "John Doe" and assign him to two classes "Art" and "Science"
When i generate the form to display class edition using laravelcollective html/forms module I'm using Form::model and pass the CoachingClass instance (of the art class) as first argument. To display field's of the related models I'm using methods like Form::input, Form::select etc. with proper names for the fields. Form displays properly and shows fields for CoachingClass model and Student model but here starts the problem. Using javascript I'm adding new instances of set of fields describing Student model fields. The problem is to save all the changes in the database while keeping the code nice and neat.
This is the example code of main form
{!! Form::model($class, ['...some code form form attributes']) !!}
<div class="form-group">
{!! Form::label('name', 'Nazwa paczki', array('class' => 'control-label')) !!}
{!! Form::text('name', null, array('class' => 'form-control', 'placeholder' => 'Nazwa paczki')) !!}
<ol id="students-list-ol">
@foreach($class->students() as $index => $student)
@include('class.student', ['student' => $student, 'index' => $index])
@endforeach
</ol>
</div>
{!! Form::close() !!}
<script type="x-template" id="student-template">
@include('class.student', ['student' => new Student(), 'index' => 9999])
</script>
<script>
document.getElementById('append-student').addEventListener('click', function () {
var count = parseInt(document.getElementById('students-list-ol').children.length) + 1;
var body = document.getElementById('student-template').innerHTML;
body = body.replace(/9999/g, count);
var p = document.createElement('div');
p.innerHTML = body;
document.getElementById('students-list-ol').appendChild(p.firstElementChild);
});
</script>
This is student form fields template
<li class="some_class_to_distinct_students_blocks">
<h1>Student</h1>
{!! Form::hidden("students[$index][id]") !!}
{!! Form::label("students[$index][name]", "Student's name")) !!}
{!! Form::text("students[$index][name]", null, array('placeholder' => 'Name and surname')) !!}
</li>
Currently my code does an crazy thing and in controller for all passed data. Example:
public function store(CoachingClass $class, Request $request){
$ids = [];
foreach($request->get('students') as $student) {
if($student['id']) {
//It has an id thus search student with that id and update him with given data
$ids[] = $student['id'];
} else {
//It hasn't an id thus let's create the student and connect him with current class
$class->students()->save(new Student($student));
}
}
//After that remove all students that aren't in the list of $ids from the $class object
}
Even bigger problem is that quite often my client's want even more nested form's. Let's say that Student has related model Note which contains all notes about the student. Of course the form should display fields for these notes to allow editing them (subject, body, date with time) and javascript to add new blocks of fields for notes (the ones which later on needs to be added not updated).
Please or to participate in this conversation.