Post For Dynamic Html Form - javascript

So this is a kind of follow up to another post I made earlier, I have this application I'm working on where I have a dynamic html form, where a user can add and remove rows. I am trying to come up with a way to capture this data when the user posts it, but I am falling short on how to do this. My idea right now is to capture a JavaScript variable from the html page that keeps track of row numbers, and capture the one row at a time, parse the row for an email, then send it to my function. Where I'm at a loss is how to capture the JavaScript variable, and from there how to I separate the rows into separate objects and loop through them. If someone can direct me towards resources that can help me resolve this or if someone can point me in the right direction, I would highly appreciate it! Please find below the html for the dynamic form, the JavaScript with this form and the post mapping for the page (the code for the post mapping is incomplete, this is really where I need aid). Thank you all in advance for any and all help!!!!
<form th:action="#{/patienthome/contact-trace-report}" method="post">
<div class="card shadow border-start-primary py-2" data-bss-hover-animate="" style="width: auto;height: auto; margin-bottom:50px;">
<div class="form-group mb-3">
<div id="formdiv-1">
<div class="row" style="margin-right:0px;margin-left:0px;padding-top:24px;">
<div class="col-md-8 offset-md-1" style="padding-right: 0px;padding-left: 0px;margin-left: 27.828px;">
<p style="margin-left: 2%;font-family: Roboto, sans-serif;font-size: 47px;text-align: left;"><strong>Contacted Individuals</strong></p>
</div>
</div>
<!-- Here html for addeable rows -->
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<table class="table table-bordered table-hover" id="tab_logic">
<thead>
<tr >
<th class="text-center">
#
</th>
<th class="text-center">
First Name
</th>
<th class="text-center">
Last Name
</th>
<th class="text-center">
Email
</tr>
</thead>
<tbody>
<tr id='addr0'>
<td>
1
</td>
<td>
<input type="text" name='firstName' placeholder='First Name' class="form-control"/>
</td>
<td>
<input type="text" name='lastName' placeholder='Last Name' class="form-control"/>
</td>
<td>
<input type="text" name='email' placeholder='Email Adress' class="form-control"/>
</td>
</tr>
<tr id='addr1'></tr>
</tbody>
</table>
</div>
</div>
<a id="add_row" class="btn btn-default pull-left">Add Row</a>
<a id='delete_row' class="pull-right btn btn-default">Delete Row</a>
</div>
<!-- Here is end of html for addeable rows -->
<div class="row d-md-flex d-xxl-flex justify-content-md-center align-items-md-center justify-content-xxl-center align-items-xxl-center" style="margin-right: 0px;margin-left: 0px;padding-top: 24px;width: auto;">
<div class="col-12 col-md-4 offset-md-4 d-xxl-flex justify-content-xxl-center align-items-xxl-center" style="width: auto;margin-left: 0;padding-left: 0;padding-right: 0px;"><button class="btn btn-light btn-lg text-center d-xxl-flex justify-content-xxl-center align-items-xxl-center" style="margin-left: 0px;width: auto;height: auto;color: rgb(255,252,252);background: rgb(231,74,59);" type="submit">Submit </button></div>
</div>
</div>
</div>
</div>
</form>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js">
</script>
<script>
var i=1;
$(document).ready(function(e){
$("#add_row").click(function()
{
$('#addr'+i).html("<td>"+ (i+1) +"</td><td><input name='firstName"+i+"' type='text' placeholder='First Name' class='form-control input-md' /></td><td><input name='lastName"+i+"' type='text' placeholder='Last Name' class='form-control input-md'></td><td><input name='email"+i+"' type='text' placeholder='Email Address' class='form-control input-md'></td>");
$('#tab_logic').append('<tr id="addr'+(i+1)+'"></tr>');
i++;
})});
$(document).ready(function(e){
$("#delete_row").click(function()
{
if(i>1)
{
$("#addr"+(i-1)).html('');
i--;
}
})});
</script>
//Post Mapping Contract Trace Report
#PostMapping("/patienthome/contact-trace-report")
public ModelAndView contractTraceReportPost(ModelAndView modelAndView, User user, #RequestParam String email, #RequestParam String firstName, #RequestParam String lastName ) throws IOException, ParseException
{
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Patient patient = patientRepo.findByEmail(authentication.getName());
//Will capture variable i from javascript so we know how many rows to capture
//Will try to capture rows as an object, then parse the email from the row
//Will then use the email to find the patient object and send it tot he list
while(i>0)
{
//capturing row as Object
//Parsing Row for email
//Need to capture as many emails as there are rows
Patient contact =patientRepo.findByEmail(email);
//Will add the user to the list
patient.addContactTraceFrom(contact);
i--;
}
modelAndView = new ModelAndView("redirect:/patienthome");
modelAndView.addObject("confirmationMessage", "Patient Profile Was Updated");
return modelAndView;
}

Related

Failed to convert value of type 'java.lang.String' to required type 'long'; For input string: "{id}"

Hello I'm doing a "CRUD web app" with Java Spring Boot and I'm trying to change my "CRUD web app" button functions from going to a new page to a modal and I'm running into problems.
First my form doesn't populate with the data that it gets from the db when I click the edit button, and second when I click Save it gives me this message.
Failed to convert value of type 'java.lang.String' to required type 'long'; nested exception is java.lang.NumberFormatException: For input string: "{id}"
My JavaScript code:
/** Modal buttons */
$(document).ready(function () {
/** Modal edit button */
$('.table .edit').on('click', function(event) {
event.preventDefault();
var href = $(this).attr('href');
$.get(href, function (student) {
$('#idEdit').val(student.id);
$('#firstNameEdit').val(student.firstName);
$('#lastNameEdit').val(student.lastName);
$('#emailEdit').val(student.email);
$('#numberEdit').val(student.number);
});
$('#editStudentModal').modal();
});
/** Modal delete button */
$('.table .delete').on('click', function(event) {
event.preventDefault();
var href = $(this).attr('href');
$.get(href, function (student) {
$('#idEdit').val(student.id);
$('#firstNameEdit').val(student.firstName);
$('#lastNameEdit').val(student.lastName);
$('#emailEdit').val(student.email);
$('#numberEdit').val(student.number);
});
$('#deleteStudentModal').modal();
});
});
My html code for the table where the edit button is:
<table class="table table-striped table-hover">
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Email</th>
<th>Phone</th>
<th sec:authorize="isAuthenticated()">Actions</th>
</tr>
</thead>
<tbody>
<tr th:each="student : ${SE_StudentList}">
<td th:text="${student.firstName}"></td>
<td th:text="${student.lastName}"></td>
<td th:text="${student.email}"></td>
<td th:text="${student.number}"></td>
<td sec:authorize="isAuthenticated()">
<a th:href="#{/showFormForUpdate_SE/{id}(id=${student.id})}" class="edit"><i class="material-icons" data-toggle="tooltip" title="Edit"></i></a>
<a th:href="#{/deleteStudent_SE/{id}(id=${student.id})}" class="delete"><i class="material-icons" data-toggle="tooltip" title="Delete"></i></a>
</td>
</tr>
</tbody>
</table>
My html code where I designed the modal form:
<!-- Edit Modal HTML -->
<div id="editStudentModal" class="modal fade">
<form th:action="#{/showFormForUpdate_SE/{id}}" method="put">
<!-- Hidden field to handle update -->
<input type="hidden" id="idEdit" name="id"/>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Edit Student</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>First Name</label>
<input type="text" class="form-control" id="firstNameEdit" name="firstName" required>
</div>
<div class="form-group">
<label>Last Name</label>
<input type="text" class="form-control" id="lastNameEdit" name="lastName" required>
</div>
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" id="emailEdit" name="email" required>
</div>
<div class="form-group">
<label>Phone</label>
<input type="text" class="form-control" id="numberEdit" name="number" required>
</div>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-default" data-dismiss="modal" value="Cancel">
<input type="submit" class="btn btn-info" value="Save">
</div>
</div>
</div>
</form>
</div>
This is my code for the update in my controller
// Update Software Engineering Student
#GetMapping("/showFormForUpdate_SE/{id}")
public String showFormForUpdate_SE(#PathVariable (value = "id") long id, Model model){
SoftwareEngineering softwareEngineering = se_service.getSEStudentById(id);
model.addAttribute("SE_Student", softwareEngineering);
se_service.saveSEStudent(softwareEngineering);
return "redirect:/softwareEngineering";
}
And this is my service for the getSEStudentById
#Override
public SoftwareEngineering getSEStudentById(long id) {
Optional<SoftwareEngineering> optional = se_repository.findById(id);
SoftwareEngineering softwareEngineering = null;
if (optional.isPresent()) {
softwareEngineering = optional.get();
} else {
throw new RuntimeException("Student not found for id ::" + id);
}
return softwareEngineering;
}
The first thing I had to do was, separate the getId method from the update method.
The reason for that was simple, I was attempting to get the Id with the GET method(which is the correct way), but when I was saving(the student) I was using the PUT method(for the form) but on the other side the EndPoint in the Controller was of GetMapping method, so I had to create a new EndPoint for the getStudentId() and also change the update Endpoint to RequestMapping and call two methods there PUT and GET.
// Get Software Engineering Student By Id
#GetMapping("/getOneSEStudent")
#ResponseBody
public SoftwareEngineering getOne(long id){
SoftwareEngineering softwareEngineering = se_service.getSEStudentById(id);
return softwareEngineering;
}
// Update Software Engineering Student
#RequestMapping(value = "/updateSEStudent", method = {RequestMethod.PUT, RequestMethod.GET})
public String showFormForUpdate_SE(SoftwareEngineering softwareEngineering){
se_service.saveSEStudent(softwareEngineering);
return "redirect:/softwareEngineering";
}

How to select laravel option in edit ajax

I have my data returning to table by ajax and in that data I also have edit form.
In my edit form I have select options which the data is dynamic and returning perfectly but I am not able to add selected attribute to saved option in database (it always shows first one)
Screenshot
As you can see in this screenshot my edit form cannot get correct option in selects.
NOTE:
If my data was returning by blade loop #foreach() I would select my correct option with something like this:
{{ $location->province_id == $province->id ? 'selected' : '' }}
<option value="{{$province->id}}" {{ $location->province_id == $province->id ? 'selected' : '' }}>{{$province->name}}</option>
but since my loop is in ajax code I cannot use that method.
Code
HTML
<table id="dataTableLocations" class="table table-striped table-bordered">
<thead>
<tr>
<th width="30">Seq No.</th>
<th>Name</th>
<th>Customer</th>
<th>Province</th>
<th>City</th>
<th>Address</th>
<th>Postal Code</th>
<th width="120">Options</th>
</tr>
</thead>
<tbody id="table_dataLocations"></tbody>
</table>
Script
I have commented my select options in code so you can find them faster
//ajax call (rest of the code
success:function(data){
// return existed data to locations
$('#table_dataLocations').html('');
$(data.locations).each(function(_, i){
var url = '{{ route("customer-locations.destroy", ":id") }}';
url = url.replace(':id', i.id);
var row = `<tr data-id="${i.id}">'+
'<td>${i.seqNo}</td>'+
'<td>${i.name}</td>'+
'<td>${i.customer.name}</td>'+
'<td>${i.province.name}</td>'+
'<td>${i.city.name}</td>'+
'<td>${i.address}</td>'+
'<td>${i.postalCode}</td>'+
'<td width="120">
<button type="button" class="btn btn-sm btn-info" data-toggle="modal" data-target="#editModal-${i.id}">
Edit
</button>
<!-- edit -->
<div class="modal fade effect-flip-horizontal editModalLocation" id="editModal-${i.id}" tabindex="-1" role="dialog" aria-labelledby="editModal-${i.id}Label">
<div class="modal-dialog" role="document">
<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" id="editModal-${i.id}Label">Edit ${i.name}</h4>
</div>
<form id="updateLocation" method="post" enctype="multipart/form-data">
#csrf
#method('PUT')
<div class="modal-body">
<div class="row" style="margin-bottom:7px;">
<div class="col-md-6">
<div class="form-group" style="width:100%">
<div class="sm-form-design">
<textarea style="width:100%" name="addressLocationUpdate" id="addressLocationUpdate" cols="30" rows="10" class="form-control" placeholder="Please enter your customer address." >${i.address}</textarea>
<label class="control-label">Address</label>
</div>
</div>
</div>
<div class="col-md-6">
<div class="row">
<div class="col-md-12 sm-form-design" style="margin-bottom:7px;">
// Provinces select
<select style="width:100%" class="form-control" name="province_idLocationUpdate" id="province_idLocationUpdate">
#foreach($provinces as $province)
<option value="{{$province->id}}">{{$province->name}}</option>
#endforeach
</select>
<label class="control-label">Province</label>
</div>
<div class="col-md-12 sm-form-design" style="margin-bottom:7px;">
// Cities select
<select style="width:100%" class="form-control" name="city_idLocationUpdate" id="city_idLocationUpdate">
#foreach($cities as $city)
<option value="{{$city->id}}">{{$city->name}}</option>
#endforeach
</select>
<label class="control-label">City</label>
</div>
<div class="col-md-12 sm-form-design" style="margin-bottom:7px;">
<div class="form-group" style="width:100%">
<div class="sm-form-design">
<input style="width:100%" type="text" value="${i.postalCode}" name="postalCodeUpdate" id="postalCodeUpdate" class="form-control" placeholder="Please enter your customer postalC code." required>
<label class="control-label">Postal Code</label>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" style="margin-bottom:7px;">
<div class="col-md-3">
<div class="form-group" style="width:100%">
<div class="sm-form-design">
<input type="text" style="width:100%" name="seqNoUpdate" id="seqNoUpdate" value="${i.seqNo}" class="form-control" placeholder="Please enter your location seqNo." required>
<label class="control-label">seqNo</label>
</div>
</div>
</div>
<div class="col-md-9">
<div class="form-group" style="width:100%">
<div class="sm-form-design">
<input type="text" style="width:100%" value="${i.name}" name="nameLocUpdate" id="nameLocUpdate" class="form-control" placeholder="Please enter your location name." required>
<label class="control-label">Name</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" data-id="${i.id}" class="btn locationUpdate btn-success">Update</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- ./Edit -->
<Form id="deleteForm" method="post" action="${url}"> #csrf #method("DELETE")<button type="submit" data-id="${i.id}" class="btn btn-sm customerDelete btn-danger">Delete</button></form>
</td>'
'</tr>`;
$('#table_dataLocations').append(row);
});
// rest of the code
Question
How can I select correct option in my edit form selects?
Update
I added loop to my code like:
$.each(data.cities, function(key, value) {
//value.id == city id
//i.city_id == locations city_id
if(value.id == i.city_id)
{
$('select[name="city_idLocationUpdate"]').append('<option value="'+ value.id +'" selected>'+ value.name +'</option>');
}
else
{
$('select[name="city_idLocationUpdate"]').append('<option value="'+ value.id +'">'+ value.name +'</option>');
}
});
This works but the issue with this is for all my locations it gets city of latest row in table and latest row itself is empty.
Example:
locations table::
row 1 = city abc
row 2 = city def
row 3 = city xyz
it shows city xyz for row 1 and 2 but row 3 is empty!
PS: here i shared screen record in case my explanation wasn't
clear enough.
You can do is to separate your table as blade and return it from ajax.
Using blade you can now target selected value.
Route::get('/ajaxTableDelete', 'Controller#myAjax');
public function myAjax() {
$province = $provinceData;
$cities= $cities;
return view('view.deleteTable', ['province'=>$province,'cities'=>$cities]->render();
}
deleteTable.blade.php
// put your table here
Through ajax
success:function(data){
$('#table_dataLocations').append(data);
}
$.each(data.cities, function(key, value) {
$('select[name="city_idLocationUpdate"]')
.append(`<option value="${value.id}" ${value.id == i.city_id ? 'selected' : ''}>${value.name}</option>`)
});
Solved
I gave up on ajax handler and brought back my #foreach to html (same as my first code above)
And then I've changed it like:
#foreach($cities as $city)
<option value="{{$city->id}}" ${`{{$city->id}}` == i.city_id ? 'selected' : ''}>{{$city->name}}</option>
#endforeach
Basically i used my php method in returned html.
${`{{$city->id}}` == i.city_id ? 'selected' : ''}
Hope it helps others.

need to create multiple groups using form in angular6

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.

document.getElementById() on a value that is set through a Meteor template

So I've been trying to build a website using Meteor and am quite new with it. I am trying to have javascript that will make use of the values on the page and then create a download from those values. These values differ depending on which page the user is on as the meteor template is loaded with specific information. The way I would think is would work is:
var thing = document.getElementById("tcpout").value;
but when I test this I get "undefined". Now if I don't do .value then do something like
console.log(document.getElementById("tcpout"));
the output in the console is this:
<td id="tcpout"> 50443</td>
where 50443 is the value that I want. Yet I can't seem to figure out how to get that into the javascript. I am using meteor and have tried a few things through meteor's project .js file, but can't seem to figure out how to incorporate dynamic fields into javascript. Essentially I just want to figure out the easiest and best way to work with the mongodb data on the client-side with javascript. Here is the template and the meteor js file.
<template name="profile">
{{#each iotdevice}}
<div class="container" style="margin-top:10px">
<div class="starter-template" align="center">
<h1>{{model}} {{manufacturer}} {{type}}</h1>
<p class="lead"></p>
<table class="table table-bordered">
<thead>
<tr>
<th>Ports</th>
<th>Outgoing</th>
<th>Incoming</th>
</tr>
</thead>
<tbody>
<tr>
<td>TCP</td>
<td id="tcpout"> {{tcpout}}</td>
<td id="tcpin"> {{tcpin}}</td>
</tr>
<tr>
<td>UDP</td>
<td id="udpout"> {{udpout}}</td>
<td id="udpin"> {{udpin}}</td>
</tr>
</tbody>
</table>
<table class="table table-bordered">
<thead>
<tr>
<th colspan="2">Domains</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{domains}}</td>
</tr>
</tbody>
</table>
</div>
<h4 align="center">Select Firewall</h4>
<div align="center">
<button style="margin-bottom:15px" type="button" class="btn btn-outline-danger" onclick="vyosformshow()">
VyOS
</button>
<button style="margin-bottom:15px" type="button" class="btn btn-outline-danger"
onclick="download('test.sh','hello\nworld')">IPTables
</button>
<button style="margin-bottom:15px" type="button" class="btn btn-outline-danger">FreePBX</button>
<button style="margin-bottom:15px" type="button" class="btn btn-outline-danger" onclick="dthings()">IPFire
</button>
<button style="margin-bottom:15px" type="button" class="btn btn-outline-danger">IPCop</button>
</div>
<div id="vyosform" style="display:none">
<form>
<div class="form-row">
<div class="form-group col-md-6">
<label for="exampleInputEmail1">firewall in name</label>
<input class="form-control" id="firein" placeholder="">
</div>
<div class="form-group col-md-6">
<label for="exampleInputPassword1">firewall out name</label>
<input class="form-control" type="text" id="fireout" placeholder="">
</div>
<div class="form-group col-md-6">
<label for="exampleInputPassword1">rule number</label>
<input class="form-control" id="rulenum" placeholder="">
</div>
<div class="form-group col-md-6">
<label for="exampleInputPassword1">device IP address</label>
<input class="form-control" id="ip" placeholder="">
</div>
<div align="center">
<button id="dostuff" class="btn btn-primary" style="margin-bottom:30px">Submit</button>
</div>
</div>
</form>
</div>
</div>
{{/each}}
</template>
JS
if (Meteor.isClient) {
//this code only runs on the client
var directory = Iron.Location.get().path;
var start = directory.lastIndexOf("/");
var stop = directory.search(".html");
var parseddir = directory.slice(start + 1, stop);
var search = directory.slice(start + 1);
var regexsearch = new RegExp(["^", search, "$"].join(""), "i");
console.log(search);
Template.iotprofiler.helpers({
'device': function () {
return DeviceList.find();
}
});
Template.profile.helpers({
'iotdevice': function () {
return DeviceList.find({model: parseddir});
}
});
Template.search.helpers({
'results': function () {
return DeviceList.find({$or: [{model: regexsearch}, {manufacturer: regexsearch}, {type: z}]});
}
});
}

Angular2 Javascript Push - Add item to array

I'm building a form in Angular2 which contains a field that is an array of objects. I've so far built the table with a Delete Row button per row and an Add Row button. These use the JavaScript push() and slice() methods.
There is a big bug though:
When adding a new row, the content of the previous rows is deleted.
That is to say, the content of the row is deleted, not the row itself.
Any ideas why?
Component Code:
public addRow(): void {
this.table.push({});
}
public deleteRow(row: object): void {
this.table.splice(this.table.indexOf(row), 1);
}
HTML Template
<form #TimesheetForm="ngForm" (ngSubmit)="saveTimesheet()">
<div class="row">
<div class="col text-right">
<button type="button" class="btn" (click)="addRow()"><i class="fa fa-plus-square" aria-hidden="true"></i> Add Row</button>
</div>
</div>
<table class="table">
<thead>
<td class="table__header">Date</td>
<td class="table__header">Time</td>
<td class="table__header">Actions</td>
</thead>
<tbody>
<tr *ngFor="let row of table">
<td class="table__item">
<input class="input" [(ngModel)]="row.date" name="date">
</td>
<td class="table__item">
<input class="input" [(ngModel)]="row.time" name="time">
</td>
<td class="table__item">
<button type="button" class="btn btn--negative" (click)="deleteRow(row)"><i class="fa fa-times" aria-hidden="true"></i> Delete</button>
</td>
</tr>
<tr *ngIf="school.rows.length == 0">
<td colspan="3">No rows exist yet. Click Add Row to start logging your timesheet.</td>
</tr>
</tbody>
</table>
</div>
<div class="row">
<div class="col">
<button class="btn btn--positive" type="submit"><i aria-hidden="true" class="fa fa-check"></i> Save</button>
</div>
<div class="col text-right">
<button class="btn btn--negative"><i aria-hidden="true" class="fa fa-times"></i> Cancel</button>
</div>
</div>
</form>
With template driven forms, we need to remember that the name attribute needs to be unique, otherwise the fields will be evaluated as the same field. So what your form does now, is not adding new form controls when you add new rows, instead it manipulates the one and same form field. If you were to put something like <pre>{{TimesheetForm.value | json}}</pre> in your template, you can see, that despite pushing new rows, there is only one form control name date and one form control named time.
So what we need to do is to provide an unique name, we can do that by using the index of the items in your table array. So do the following:
<tr *ngFor="let row of table; let i = index">
<td>
<input [(ngModel)]="row.date" name="date{{i}}">
</td>
<td>
<input [(ngModel)]="row.time" name="time{{i}}">
</td>
<!-- more code here -->
</tr>

Categories

Resources