I have a form with 2 fields with an add row button. When this button is clicked it simply clones the row and adds another row consisting of the 2 form fields. How do I save these newly added fields in my ajax post? Right now, it only ever saves the last row in my form.
<form action="." method="post">
<table class="table table-condensed" id="pa">
<thead>
<tr>
<th class="col-xs-2">Description</th>
<th class="col-xs-2">Expected %</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="form-group">
<input class="text-box single-line" data-val="true" data-val-required="The Description field is required." id="Description" name="Description" value="" type="text">
</div>
</td>
<td>
<div class="form-group">
<div class="input-group">
<input class="text-box single-line" data-val="true" data-val-number="The field Expected must be a number." id="Expected" name="Expected" value="100" type="number">
</div>
</div>
</td>
<td class="vert-align"> <a class="btn btn-danger btn-xs remove-row-pa">x</a>
</td>
</tr>
</tbody>
</table>
<div class="pull-right">
<p> <a href="#" id="add-pa-row" class="btn btn-success btn-xs">
<i class="fa fa-plus-circle"></i> Add row
</a>
</p>
</div>
<div class="form-group">
<p>
<input value="Save" class="btn btn-success" type="submit">
</p>
</div>
</form>
function Qs2Dict(qs) {
var pairs = qs.split('&');
var dict = {};
pairs.forEach(function (pair) {
var kv = pair.split('=');
dict[kv[0]] = decodeURIComponent(kv[1].replace(/\+/g, "%20"));
});
return dict;
}
// Add row
$("#add-row").click(function () {
$('#pa tbody>tr:last').clone(true).insertAfter('#pa tbody>tr:last');
$('#pa tbody>tr:last #Description').val('');
$('#pa tbody>tr:last #Expected').val('');
return false;
});
$('#modal').click(function (e) {
e.preventDefault();
var url = $(this).data('url');
var data = $('form').serialize();
var dict = Qs2Dict(data);
$.ajax({
type: "POST",
url: url,
data: {
"Description": dict.Description,
"EffectiveDate": dict.EffectiveDate,
"Expected": dict.Expected,
},
success: function (result) {},
});
});
Change their name attribute, since it defines/enumerates the fields to save.
If they are equal, which they are if you clone, only the last one is taken.
Or use arrays i.e. name="Expected[]"
EDIT: more specifically: I assume they get "lost" due to above reason during $('form').serialize();
Related
I have a table
<form id="project-form">
<table id="project-table" class="table table-striped table-inverse table-responsive">
<caption>Projects</caption>
<thead class="thead-inverse">
<tr>
<th scope="col">#</th>
<th scope="col">Project name</th>
<th scope="col">Description</th>
<th scope="col">Estimated time (min)</th>
<th scope="col">Actual time (min)</th>
<th scope="col">Add task</th>
<th scope="col">Delete project</th>
</tr>
</thead>
<tbody id="project-body">
</tbody>
</table>
</form>
This table is filled with data from an AJAX GET request
function getProjects() {
$.ajax({
method: 'GET',
dataType: 'json',
data: {
functionToCall: 'project',
},
url: 'http://localhost/WBS/php/api/requests/get.php',
success: (response) => {
$.each(response, function () {
$.each(this, function (index, value) {
$('#project-body').append(
`
<tr>
<td>
<input class="form-control" type="hidden" name="projectid" id="projectid" value="${value.projectid}">
</td>
<td>
<input class="form-control" type="text" name="projectName" id="projectName" value="${value.title}">
</td>
<td>
<input class="form-control" type="text" name="description" id="description" value="${value.description}">
</td>
<td>
<input class="form-control" type="text" name="estimatedTime" id="estimatedTime" value="${value.Estimated_time}">
</td>
<td>
<input class="form-control" type="text" name="actualTime" id="actualTime" value="${value.Actual_time}">
</td>
<td>
<a id="addTask" class="btn btn-info" href="Overview.html?id=${value.projectid}" role="button">
<i class="fa fa-angle-right" aria-hidden="true"> </i> Add task
</a>
</td>
<td>
<button type="button" id="deleteProject" name="deleteProject" class="btn btn-danger">
<i class="fa fa-angle-right" aria-hidden="true"> </i> Delete project
</button>
</td>
</tr>
`
);
});
});
},
error: () => {
console.error('Something went wrong with the getProjects function');
},
});
}
There is also the option to dynamically add a new row of inputs to the table
function addProject() {
event.preventDefault();
$('#project-body').append(
`
<tr>
<td>
<input class="form-control" type="hidden" name="projectid" id="projectid" >
</td>
<td>
<input class="form-control" type="text" name="projectName" id="projectName">
</td>
<td>
<input class="form-control" type="text" name="description" id="description">
</td>
<td>
<input class="form-control" type="text" name="estimatedTime" id="estimatedTime">
</td>
<td>
<input class="form-control" type="text" name="actualTime" id="actualTime">
</td>
<td>
<a id="addTask" class="btn btn-info" href="Overview.php" role="button">
<i class="fa fa-angle-right" aria-hidden="true"> </i> Add task
</a>
</td>
<td>
<button type="button" id="deleteProject" name="deleteProject" class="btn btn-danger">
<i class="fa fa-angle-right" aria-hidden="true"> </i> Delete project
</button>
</td>
</tr>
`
);
}
I submit all of my data on this button
<button id="saveProjects" form="project-form" class="btn btn-info" type="button"><i class="fa fa-angle-right" aria-hidden="true"></i> Save changes</button>
In the document ready I handle all of my onclick events
$(document).ready(() => {
$('#saveProjects').on('click', () => {
uploadProjects();
});
$('#addProject').on('click', () => {
addProject();
});
});
On my PHP side I have a class that handles all of my POST requests, inside of this class is a function that will handle the uploading of new projects
public function uploadProject()
{
try {
$title = $_POST["projectName"];
$description = $_POST["description"];
$estimatedTime = $_POST["estimatedTime"];
$actualTime = $_POST["actualTime"];
$stm = $this->pdo->getCon();
$PDOStatement = $stm->prepare("INSERT INTO projects (title,description,Estimated_time,Actual_time) VALUES(:title,:description,:Estimated_time,:Actual_time)");
$PDOStatement->bindParam(':title', $title, PDO::PARAM_STR);
$PDOStatement->bindParam(':description', $description, PDO::PARAM_STR);
$PDOStatement->bindParam(':Estimated_time', $estimatedTime, PDO::PARAM_STR);
$PDOStatement->bindParam(':Actual_time', $actualTime, PDO::PARAM_STR);
$PDOStatement->execute();
header('HTTP/1.1 200 OK');
} catch (Exception $th) {
header("HTTP/1.0 404 Not Found");
throw $th->getMessage();
}
}
Now debugging my PHP code, and all the data I receive in the POST array will always correspond to the first row in the table, for example:
Let's say i have a existing row inside of my table with the values of : Project name = Hello | Description = World.
I click on the add project button and a new row is added to the table, I fill in the inputs inside of the row with something like this : Project name = Second table row | Description = Second description.
At the back-end I will always receive the values of Hello and World and not the values of the newest added row inside of the table.
I googled around a bit and only saw examples on how to the value of a SINGLE dynamically added input and not a new row.
I think you can rename your inputs like:
name="projectid[]"
Then PHP will receive an array of those values:
$total = count($_POST["projectid"]);
for ($i = 0; $i < $total; $i++) {
$title = $_POST["projectName"][$i];
$description = $_POST["description"][$i];
$estimatedTime = $_POST["estimatedTime"][$i];
$actualTime = $_POST["actualTime"][$i];
// Your INSERT query is performed here
}
I need to create multiple groups in the form. when i create a childgroup and enter an input value the same value reflect in another group i known this is due to ngModel but how to overcome this issue. there is another issue i am facing under childGroup there is 2 table when i create another childGroup and add a new table row to that childGroup this will reflect in another childGroup also.
HTML
<fieldset *ngFor="let task of tasks; let a = index">
<legend>childGroup</legend>
<button (click)="deleteRow(a)" class="btn btn-sm btn-circle btn-danger actionMargin rmv-btn">X</button>
<div class="row">
<section class="col col-6">
<label class="label">Name</label>
<label class="input">
<input type="text" class="input-sm" [(ngModel)]="task.Name" name="task[a].Name" required>
</label>
</section>
<section class="col col-6">
<label class="label">Comm</label>
<label class="input">
<input type="text" class="input-sm" [(ngModel)]="task.Config.command" name="task[a].Config.command" required>
</label>
</section>
</div>
<!--Table-->
<section>
<h2>ABC</h2>
<table class="table table-bordered">
<thead>
<tr>
<th class="name">S no.</th>
<th class="name">Label</th>
<th class="name">Value</th>
<th class="name">Dynamic</th>
<th class="name">Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of task.ports; let i = index">
<td align="center"><label>{{i + 1}}</label></td>
<td><input type="text" [(ngModel)]="item.Label" name="item[i].Label" [ngModelOptions]="{standalone: true}"
class="inputborder" required></td>
<td><input type="number" [disabled]="item[i].boolean" [(ngModel)]="item[i].Value" name="item.Value"
[ngModelOptions]="{standalone: true}" class="inputborder" required></td>
<td><input type="checkbox" [(ngModel)]="item[i].boolean" name="item[i].boolean" class="check"
[ngModelOptions]="{standalone: true}" required><span class="yes">Yes</span></td>
<td align="center"><button (click)="deleteRow(i,'port')" placement="top" tooltip="Remove Port" class="btn btn-sm btn-circle btn-danger actionMargin rmv-btn">X</button></td>
</tr>
</tbody>
</table>
<button type="button" (click)="Addrow('port')" placement="top" tooltip="Add Port" class="btn btn-sm btn-primary posi">Add
abc</button>
</section>
</fieldset>
TS.
tasks= [];
taskObj = { //click on a blue + button i am pushing this object to tasks
Name: "",
Config: {
command: ""
},
artifacts : [],
ports : []
};
// to add a table row
Addrow(i) {
if (i == 'port') {
let num = 0;
this.taskObj.ports.push({
Label: '',
Value: num,
boolean: true
});
} else {
this.taskObj.artifacts.push({
Source: '',
Relative: ''
})
}
console.log(this.tasks);
}
//remove the table row
deleteRow(index, i) {
if (i == "port") {
this.taskObj.ports.splice(index, 1);
} else {
this.taskObj.artifacts.splice(index, 1);
}
}
I the HTML code i have not add 'XYZ' table code because its same as 'ABC' table. how to implement validation to this loop within loop. Please help me with this issue.
basically the objective of this request is to have a modal table that adds new table row/cells and pass the value of "var OBGyneID = $(this).attr("id"); " to first cell and value of "var billing_id = newID;" to second cell whenever new rows/cells is/are added. Seeking your help, thanks!
* MY MODAL*
<div id="myModal" class="modal fade card new-contact myModal" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="card profile">
<div class="profile__img">
<img src="img/profile2.jpg" alt="">
</div>
<div class="profile__info">
<h3 style="text-transform:capitalize;" id="pxname" name="pxname"></h3>
<ul class="icon-list">
<li>LAST <p name="consdates" id="consdates"></p></li>
<li>Last visit: </li>
<li><i class="zmdi zmdi-twitter"></i> #mallinda-hollaway</li>
</ul>
</div>
</div>
<div>
<div class="table-responsive">
<table id="billingTable" class="table table-inverse table-sm table-hover table-condensed" style="font-size:120%">
<thead>
<th>OBDYID</th>
<th>CK</th>
<th>PROCEEDURE</th>
<th>AMOUNT</th>
</thead>
<tbody id="billing_body" style="text-transform:capitalize;">
<form method="get" id="insert_form">
<tr>
<td width="10%"><input type="text" style="width:100%;" id="OBGyneID" name="OBGyneID"></td>
<td width="10%"><input type="text" style="width:100%;" id="AssessMentEntryID" name="AssessMentEntryID"></td>
<td width="60%"><input type="text" style="width:100%;" class="ExamDesc" type="text" id="ExamDesc" name="ExamDesc"></td>
<td width="20%"><input type="text" style="width:100%;" class="Price" type="text" id="Price" name="Price"></td>
</tr>
</form>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<input type="submit" name="insert" id="insert" value="Insert" class="btn btn-success" />
<input type="submit" id="addRow" value="add" name="add" class="btn btn-info" />
<button type="button" class="btn btn-link" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
* MY JS to add new rows/cells*
$(document).ready(function () {
$("#addRow").click(function () {
$("#billingTable").append('<tr><td width="10%"><input type="text" style="width:100%;" id="OBGyneID" name="OBGyneID" ></td>'+
'<td width="10%"><input type="text" style="width:100%;" id="AssessMentEntryID" name="AssessMentEntryID"></td>'+
'<td width="60%"><input type="text" style="width:100%;" class="ExamDesc" type="text" id="ExamDesc" name="ExamDesc"></td>'+
'<td width="20%"><input type="text" style="width:100%;" class="Price" type="text" id="Price" name="Price"></td></tr>');
jQuery(".ExamDesc").autocomplete({
source: 'php/billingentry.php'
});
});
});
* Pass values to Modal * this will only pass value when modal pops-up but cant pass value whenever new rows/cells are added.
$(document).on('click', '.billing_data', function(){
var OBGyneID = $(this).attr("id");
var newID = new Date().getUTCMilliseconds();
var billing_id = newID;
$.ajax({
url:"php/billing_fetch.php",
method:"GET",
data:{OBGyneID: OBGyneID},
dataType:"json",
success:function(data){
$('#AssessMentEntryID').val(data.AssessMentEntryID);
$('#ExamDesc').val(data.ExamDesc);
$('#Price').val(data.Price);
$('#pxservice').val(data.pxservice);
$('#companyname').val(data.companyname);
$('#chiefcomplain').val(data.chiefcomplain);
document.getElementById("OBGyneID").value = OBGyneID;
document.getElementById("AssessMentEntryID").value = billing_id;
document.getElementById("pxname").innerHTML = (data.fname)+" "+(data.mi)+" "+(data.lname);
document.getElementById("consdates").innerHTML = (data.obgyneDate);
$('#myModal').modal('show');
}
});
});
whenever you are adding a new row HTML in billing table, you are using the same id for OBGyneID, AssessMentEntryID,ExamDesc and Price. And if you added two rows, DOM will not be able to work properly as there are multiple same ids out there. So I will suggest you to replace that with class and use class name to set values. Check below code:
$(document).ready(function () {
$("#addRow").click(function () {
$("#billingTable").append('<tr><td width="10%"><input type="text" style="width:100%;" class="OBGyneID" name="OBGyneID" ></td>'+
'<td width="10%"><input type="text" style="width:100%;" class="AssessMentEntryID" name="AssessMentEntryID"></td>'+
'<td width="60%"><input type="text" style="width:100%;" class="ExamDesc" type="text" name="ExamDesc"></td>'+
'<td width="20%"><input type="text" style="width:100%;" class="Price" type="text" name="Price"></td></tr>');
jQuery(".ExamDesc").autocomplete({
source: 'php/billingentry.php'
});
});
});
One you have added HTML code, then you can find out last row of billingTable and can set vales in that. Check below code:
$(document).on('click', '.billing_data', function(){
var OBGyneID = $(this).attr("id");
var newID = new Date().getUTCMilliseconds();
var billing_id = newID;
$.ajax({
url:"php/billing_fetch.php",
method:"GET",
data:{OBGyneID: OBGyneID},
dataType:"json",
success:function(data){
$("#billingTable").find(".AssessMentEntryID:last").val(data.AssessMentEntryID);
$("#billingTable").find(".ExamDesc:last").val(data.ExamDesc);
$("#Price").find(".Price:last").val(data.Price);
$("#billingTable").find(".consdates:last").html(data.obgyneDate);
//and so on
$('#myModal').modal('show');
}
});
});
Also, I would suggest you to use HTMl template tag for making clone for row. Appending HTML in JS is not a recommended way. Hope it helps you.
I used JavaScript to clone and add rows. How can separate validation be done for each row?
var i = 0;
function cloneRow() {
var row = document.getElementById("clone");
var table = document.getElementById("data");
var selectIndex = 1;
var clone = row.cloneNode(true);
table.appendChild(clone);
clone.setAttribute("style", "");
}
function deleteRow(btn) {
var result = confirm("Do you Want to delete this ?");
if (result) {
var row = btn.parentNode.parentNode;
row.parentNode.removeChild(row);
}
}
<div class="row">
<div class="col-sm-12">
<div class="col-sm-7"></div>
<div class="col-sm-2">
<button type="button"class="btn btn-primary default btn-xs" onclick="cloneRow()" >add more...</button>
</div>
</div>
</div><br><br>
<div class="row" id ="close">
<div class="col-sm-4"></div>
<div class='col-sm-4'>
<form id="NAME_VALUE" method="POST">
<table class="table-striped">
<tbody id="data">
<tr id ="clone" style="display:none;">
<td>
Name :<input type="text" name="INPUT_NAME" style="width:100px;" id="name" name="INPUT_NAME">
</td>
<td>
Value :<input type="text" name="INPUT_VALUE" style="width:100px;" id="value" name="INPUT_VALUE">
</td>
<td>
<button type="button"class="btn btn-primary default btn-xs" name ="delete" style="margin-left: 5px;" onclick="deleteRow(this); return false;">
<span class="glyphicon glyphicon-remove-circle" style="text-align:center" ></span>
</button>
</td>
</tr>
<tr>
<td>
Name :<input type="text" name="INPUT_NAME" style="width:100px;" id="name" name="INPUT_NAME">
</td>
<td>
Value :<input type="text" name="INPUT_VALUE" style="width:100px;" id="value" name="INPUT_VALUE">
</td>
<td>
<button type="button"class="btn btn-primary default btn-xs" name ="delete" style="margin-left: 5px;" onclick="deleteRow(this); return false;">
<span class="glyphicon glyphicon-remove-circle" style="text-align:center" ></span>
</button>
</td>
</tr>
</tbody>
</table><br>
<button type="button"class="btn btn-primary default btn-xs" style="margin-left: 5px;" onclick="submit_login(); return false;"> save.</button>
</form>
</div>
</div>
I'd like to create this type of validation for every row or <tr>.
When the add button is clicked a new input is dynamically added. However when the form is submitted only the first input field is validated. How can I validate the dynamically added inputs?
If you want to separate the validation for each row - you should create a row constructor.
Basically when you clone a new row - you clone the constructor with all its methods inside.
var Row = function () {
this.name = "";
this.value = "";
//add more properties
}
Create the methods:
Row.prototype.verify = function () {
return this.name !== `undefined` && this.value !== `undefined`;
}
In your clone function you just have to call it:
var rowInstance = new Row();
And you can use it like that:
if (rowInstance.verify()) {
//if the row information is valid then do something
}
how can do separate validation in each row in java script i used in clone for add more function but i can't do validation for every row.how is this ?
help me
var i = 0;
function cloneRow() {
var row = document.getElementById("clone");
var table = document.getElementById("data");
var selectIndex = 1;
var clone = row.cloneNode(true);
table.appendChild(clone);
clone.setAttribute("style", "");
}
function deleteRow(btn) {
var result = confirm("Do you Want to delete this ?");
if (result) {
var row = btn.parentNode.parentNode;
row.parentNode.removeChild(row);
}
}
<div class="row">
<div class="col-sm-12">
<div class="col-sm-7"></div>
<div class="col-sm-2">
<button type="button"class="btn btn-primary default btn-xs" onclick="cloneRow()" >add more...</button>
</div>
</div>
</div><br><br>
<div class="row" id ="close">
<div class="col-sm-4"></div>
<div class='col-sm-4'>
<Form id="NAME_VALUE" method="POST" >
<table class="table-striped" >
<tbody id="data">
<tr id ="clone" style="display:none;">
<td>
Name :<input type="text" name="INPUT_NAME" style="width:100px;" id="name" name="INPUT_NAME">
</td>
<td>
Value :<input type="text" name="INPUT_VALUE" style="width:100px;" id="value" name="INPUT_VALUE">
</td>
<td>
<button type="button"class="btn btn-primary default btn-xs" name ="delete" style="margin-left: 5px;" onclick="deleteRow(this);
return false;">
<span class="glyphicon glyphicon-remove-circle" style="text-align:center" ></span></button>
</td>
</tr>
<tr>
<td>
Name :<input type="text" name="INPUT_NAME" style="width:100px;" id="name" name="INPUT_NAME">
</td>
<td>
Value :<input type="text" name="INPUT_VALUE" style="width:100px;" id="value" name="INPUT_VALUE">
</td>
<td>
<button type="button"class="btn btn-primary default btn-xs" name ="delete" style="margin-left: 5px;" onclick="deleteRow(this);
return false;">
<span class="glyphicon glyphicon-remove-circle" style="text-align:center" ></span></button>
</td>
</tr>
</tbody>
</table><br>
<button type="button"class="btn btn-primary default btn-xs" style="margin-left: 5px;" onclick="submit_login();
return false;"> save.</button>
</Form>
</div>
</div>
$(document).ready($.validator.addMethod("valueNotEquals", function (value, element, arg) {
return arg != value;
},
"Value must not equal arg."));
$(function () {
$("#NAME_VALUE").validate({
errorClass: "validation-error-class",
// Specify the validation rules
rules: {
INPUT_NAME: {
required: true,
maxlength: 64
},
INPUT_VALUE: {
required: true,
maxlength: 64
}
},
// Specify the validation error messages
messages: {
INPUT_NAME: {
required: "[your name ?]",
maxlength: "[Your name cannot exceed 64 characters]"
},
INPUT_VALUE: {
required: "[ value ?]",
maxlength: "[Your password cannot exceed 64 characters]"
}
},
errorElement: "div",
wrapper: "div",
errorPlacement: function (error, element) {
error.appendTo(element.parent("td"));
error.css('color', 'red');
error.css('text-align', 'center');
}
});
});
function submit_login( )
{
if ($("[id='name'],[id='value']").valid()) {
alert("Successfully saved");
}
}
i like to create this type of validation every row or tr so please help me..]1]1
i put this one but if i write in one text field every validation gone..