So, I've been trying to provide a user interface in an html page whereby the user can type a number in an input field and hit apply (using addRowsForm), to see rows of various input fields being appended to another separate form (named createRecordForm) and later submit this form (including all those appended inputs and two other hidden fields) via ajax.
My problem is that I cannot find a way to group the data and post it due to the unpredictable number of input fields that would be added, depending on the user's interaction with the page. Your help is greatly appreciated.
Here are my codes:
addRowsForm
<form action="#" name="addRowsForm" id="addRowsForm" method="post">
<div class="form-group">
<input type="number" min="1" max="10" name="addRowCounter" id="addRowCounter">
</div>
<button type="submit" name="applyBtn" id="applyBtn">Apply</button>
</form>
createRecordForm
<table class="table table-bordered table-striped table-sm">
<thead class="bg-brand-4th-color">
<th>Link Type</th>
<th>Link</th>
<th>Recorded Time</th>
<th>Video Visibility</th>
</thead>
<form action="" method="POST" name="createRecordForm" id="createRecordForm">
<input type="hidden" name="ats_id" value="{{atsIdForFrag}}">
<input type="hidden" name="tot_rows" value="">
<tbody id="tBody">
</tbody>
<tfoot>
{# submit btn #}
<tr>
<td colspan="4">
<div class="form-group">
<button class="btn btn-success" type="submit" name="create_recorded_session_btn" id="create_recorded_session_btn">Create</button>
</div>
</td>
</tr>
</tfoot>
</form>
</table>
Javascript part:
<script>
$( document ).ready(
function(){
$("#addRowsForm").on("submit", function(e) {
e.preventDefault();
var rowCounter = $("input[name=addRowCounter]").val();
$("input[name=tot_rows]").val(rowCounter);
//reset any previous content
$("#tBody").html('');
for (var i = 1; i <= rowCounter; i )
{
var newRowContent =
"<tr><td><div class='form-group p-0 m-0'><select class='form-control' name='link_type_row_" i "' required><option value='google_drive' selected>Google Drive</option></select></div></td><td><div class='form-group p-0 m-0'><input class='form-control' type='text' name='link_row_" i "' value='' required></div></td><td><div class='form-group p-0 m-0'><input type='datetime-local' name='datetime_row_" i "' class='form-control' required/></div></td><td><div class='form-check'><input class='form-check-input' type='radio' name='visibilityRadio_row_" i "' id='showOption_row_" i "' value='show'><label class='form-check-label' for='showOption_row_" i "'>Show to student</label></div><div class='form-check'><input class='form-check-input' type='radio' name='visibilityRadio_row_" i "' id='dontShow_row_" i "' value='dont_show'><label class='form-check-label' for='dontShow_row_" i "'>Don\'t show to student</label></div></td></tr>";
$("#tBody").append(newRowContent);
}
$("#createRecordForm").on("submit", function(e) {
e.preventDefault();
var ats_id = $("input[name=ats_id]").val();
var tot_rows = $("input[name=tot_rows]").val();
// here is my broblem, I need to change this hard-coded lines into dynamic data and process it in php
var link_type_row_1 = $("select[name=link_type_row_1]").val();
var link_row_1 = $("input[name=link_row_1]").val();
var datetime_row_1 = $("input[name=datetime_row_1]").val();
var visibilityRadio_row_1 = $("input[name=visibilityRadio_row_1]:checked").val();
var link_type_row_2 = $("select[name=link_type_row_2]").val();
var link_row_2 = $("input[name=link_row_2]").val();
var datetime_row_2 = $("input[name=datetime_row_2]").val();
var visibilityRadio_row_2 = $("input[name=visibilityRadio_row_2]:checked").val();
var url = "{{ path('ao__frg_persist_st_rec_session')|escape('js') }}";
var type = "POST";
$.ajax({
url : url,
type: type,
data : {
'ats_id': ats_id,
'tot_rows': tot_rows,
'link_type_row_1': link_type_row_1,
'link_row_1': link_row_1,
'datetime_row_1': datetime_row_1,
'visibilityRadio_row_1': visibilityRadio_row_1,
'link_type_row_2': link_type_row_2,
'link_row_2': link_row_2,
'datetime_row_2': datetime_row_2,
'visibilityRadio_row_2': visibilityRadio_row_2
},
success: function(returnedMsg) {
// do something
}
});
});
});
});
</script>
[UPDATE : Check my answer below this paragraph] If I implement the batch approach as suggested by @Kinglish, I will end up having a big single radio while each row should have its own radio input separately from the rest.
[SOLUTION TO THE UPDATE ISSUE ABOVE] So I used the loop index number to remain the unique name and ID for each row's radio inputs. Now the row 1 has input name/id of visibilityRadio_row_1 and 2nd row's name/id is visibilityRadio_row_2. Then I used the ^ wildcard selector and the :checked property to target the value of the checked radio in each row independent of other rows.
let obj = [];
$('.data-group').each(function() {
obj.push({
link_type: $(this).find('select[name="link_type_row"]').val(),
link: $(this).find('input[name="link_row"]').val(),
created_at: $(this).find('input[name="datetime_row"]').val(),
is_active: $(this).find('input[name^="visibilityRadio_row"]:checked').val()
})
})
CodePudding user response:
I would approach this differently. Consider that you can process these in batches, rather than a finite loop. Without rewriting your script, look at how these are processed. you end up with an array of objects that appear in the order they are in your form. This does away with the messy bit of appending a number to each field. In your remote script that receieves these, you can just iterate through them and, if desired, add the number at that point.
$(document).ready(function() {
$('.submit').click(function() {
let obj = [];
$('.data-group').each(function() {
obj.push({
name: $(this).find('input[name="name"]').val(),
gender: $(this).find('select[name="gender"]').val(),
favorite_color: $(this).find('input[name="favorite_color"]').val()
})
})
console.log('obj:', obj);
})
})
// I accidentally did this in vanillaJS first, so for posterity, here is that version:
/*
window.addEventListener('DOMContentLoaded', () => {
document.querySelector('.submit').addEventListener('click', () => {
let obj = [];
document.querySelectorAll('.data-group').forEach(e => {
obj.push({
name: e.querySelector('input[name="name"]').value,
gender: e.querySelector('select[name="gender"]').value,
favorite_color: e.querySelector('input[name="favorite_color"]').value
})
})
console.log('obj:', obj);
})
})
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='data-group'>
<input name='name' value='john' />
<select name='gender'>
<option selected value='this'>this</option>
<option value='that'>that</option>
<option value='other'>other</option>
</select>
<input name='favorite_color' value='blue' />
</div>
<div class='data-group'>
<input name='name' value='mary' />
<select name='gender'>
<option value='this'>this</option>
<option value='that' selected>that</option>
<option value='other'>other</option>
</select>
<input name='favorite_color' value='green' />
</div>
<hr>
<button class='submit'>click</button>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>