I have a form which allows a user to add a new course title and gives them the option to add more record making it more convenient instead of submitting each one separately.
I've attempted to use syntax which I've seen in a number of examples online and it works in adding extra rows dynamically however this affects the form submission when it connects to the mysql database.
It will add the first record however not the second and I'm not sure if I'm executing it correctly using PDO.
if anyone could provide some insight as to how i can achieve this and why my code is failing i would be much appreciative.
the php file:
<?php
include "db_conx.php";
try
{
$db_conx = new PDO("mysql:host=$mysql_hostname;dbname=$mysql_dbname", $mysql_username, $mysql_password);
$db_conx->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = $db_conx->prepare("INSERT INTO `insights`.`course_details` (`course_title`) VALUES (:course_title)");
$course_title = $_POST['course_title'];
//$course_code = $_POST['course_code'];
$sql->bindParam(':course_title', $course_title, PDO::PARAM_STR);
//$sql->bindParam(':course_code', $course_code, PDO::PARAM_STR);
/*** execute the prepared statement ***/
$courses = array();
if ($sql->execute()) {
$courses[] = $sql;
}
}
/*** success message ***/
$message = "<p class='text-success'> Record Successfully Added <span class='glyphicon glyphicon-ok'/></p>";
}
catch(Exception $e)
{
$message = 'Message: ' .$e->getMessage();
}
die($message);
?>
the AJAX which adds more rows when clicked and submits the form when 'submit' is clicked:
function addCall() {
var data = $('#addForm').serialize();
$.post('ManageCourses_AddSubmit.php', data, function(response){
$("#addForm").html(response);
//'soft'reload parent page, after a delay to show message
setTimeout(function(){
$('#addModal').modal('hide')
location.reload();
},3500);
}).fail(function(jqXHR, textStatus) {
alert( "Request failed: " + textStatus );
});
}
jQuery(function($){
var i = 1;
var $button = $('#add_row'),
$row = $('.addForm').clone();
$button.click(function(){
$row.clone().insertBefore( $button );
});
});
the form where the data is sent from:
<div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-labelledby="addModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Add New Record: </h4>
</div>
<div class="modal-body">
<form id="addForm" class="addForm">
<div class="form-group">
<label for="course_code" class="pull-left" class="control-label">Course Code:</label>
<input type="text" class="form-control" id="course_code_id" name="code[]" readonly value ="NULL">
</div>
<div class="form-group">
<label for="course_name" class="pull-left" class="control-label">Course Title:</label>
<input type="text" class="form-control" placeholder="Enter Course Title" id="course_title_id" name="course_title">
</div>
</form>
</div>
<div class="modal-footer">
<div class="btn-toolbar">
<button type="button" class="btn btn-primary" id="add_row" name="add_row">Add New Record <span class="glyphicon glyphicon-plus"></button>
<button type="button" class="btn btn-danger" id="del_row" name="del_row">Delete Row <span class="glyphicon glyphicon-trash"></button>
<button type="button" class="btn btn-default" class="pull-right" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-success" class="pull-right" onclick="addCall();">Submit <span class="glyphicon glyphicon-saved"></button>
</div>
</div>
</div>
</div>
</div>
thank you! :)
Your problem is coming from targeting an element id in the following line:
var data = $('#addForm').serialize();
First off, you should always treat the id attribute as if it only exists in one location of the DOM. For more information, see:
http://www.w3.org/TR/2011/WD-html5-20110525/elements.html#the-id-attribute
To fix your problem, you need to pass the data from each element and handle the data differently on the backend. In your JavaScript, change the following line:
var data = $('#addForm').serialize();
to:
var data = {};
var index = 0;
// use the class of the form elements instead
$('.addForm').each(function(){
// take each form value an store it within the data variable
data['course_code'][index] = $(this).find('input[name=course_code]').val();
data['course_title'][index] = $(this).find('input[name=course_title]').val();
index++;
});
Now, you need to update your backend to accept the new array of values...
<?php
include "db_conx.php";
try
{
$db_conx = new PDO("mysql:host=$mysql_hostname;dbname=$mysql_dbname", $mysql_username, $mysql_password);
$db_conx->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$courses = array();
// check if we have valid post data
if(isset($_POST['course_code']) && isset($_POST['course_title']))
{
foreach($_POST['course_code'] as $index=>$course_code)
{
// check if we have a matching title (needed for the title insert)
$course_title = '';
if(isset($_POST['course_title'][$index]))
$course_title = $_POST['course_title'][$index];
else
continue; // no title found, skip to the next index
// at this point, use $course_title and $course_code in your query
$sql = $db_conx->prepare("INSERT INTO `insights`.`course_details` (`course_title`, `course_code`) VALUES (:course_title, :course_code)");
$sql->bindParam(':course_title', $course_title, PDO::PARAM_STR);
$sql->bindParam(':course_code', $course_code, PDO::PARAM_STR);
/*** execute the prepared statement ***/
if ($sql->execute()) {
$courses[] = $sql;
}
}
}
/*** success message ***/
$message = "<p class='text-success'> Records Successfully Added <span class='glyphicon glyphicon-ok'/></p>";
}
catch(Exception $e)
{
$message = 'Message: ' .$e->getMessage();
}
die($message);
?>