Issue
As I said in the title, I need to create a table in which every cell has a numeric input. So I created a component and I want to capture in the ts file what the user inserted in every cell (I also need to know in which cell he inserted the data too). In addition, the table should have a scalable number of rows(I need to populate the table with data from db, so please let me know if there is a way to precompile it)
Here I have added the html I tried even though it’s not enough to do what I want to do.
<form #login="ngForm" (ngSubmit)="submit(login.value)" novalidate>
<table class="rtable">
<tr>
<th></th>
<th *ngFor="let column of months">
{{column}}
</th>
</tr>
<tr *ngFor="let row of FigProfs">
{{row.nome}}
<td *ngFor="let column of mesi">
<input type="number" #{{column}}_{{row}}="ngModel" required name="{{column}}_{{row}}" class="formControl" ngModel>
</td>
</tr>
</table>
<button class="btnsubmit" type="submit">GO</button>
This table has months in the heading and some characteristics on the left side. I need to let the user edit the cell of the table and I have to bring this information to my ts code, example:
"january/characteristic x -> data written from the user " ;
so I want to have in my ts all the data that I inserted down here (the heigth of the table is variable so I cannot insert form controls for the many inputs I have in the pic rn)
I know this code is probably completely wrong but I don’t know how to do it in an easier way.
Thank you in advice for your help, I really appreciate it.
Solution
Well done. Thank you for adding some code. For reference, I really just used information from Angular’s Reactive Forms below.
I did want to re-use some of your sample code, but unfortunately couldn’t get it to adapt in a logical way. But you should be able to use the below to get it adapted as you need it.
My assumption is that you are using the Angular CLI to generate your components, and thus your .ts and .html are already referenced and created properly. In your something.component.ts, you will need to add something similar to:
import { FormGroup, FormControl } from '@angular/forms';
import { Component, OnInit } from '@angular/core';
//Create an interface for the data
interface testIntf {
index: string,
fname: string,
lname: string,
}
...skipping the existing stuff...
export class SomethingComponent implements OnInit {
//Some sample data for headings
headings = ["Index", "First name", "Surname"];
//Some sample data for the form to be pre-filled. Note the use of the interface. Going forward you will likely import your data using Observables.
dataArray: testIntf[] = [
{"index": "1", "fname": "Test", "lname": "One"},
{"index": "2", "fname": "Tester", "lname": "Two"},
{"index": "3", "fname": "", "lname": ""},
{"index": "4", "fname": "", "lname": ""},
]
//Your form related stuff!!
//Note where this matches in the html
//Create an empty form
dataForm = new FormGroup({});
//Note that ngOnInit must be imported and implemented above
ngOnInit(): void {
this.generateControls(this.dataArray);
}
//Add controls based on number of entries in array
generateControls(x: testIntf[]) {
var y = x.length
for (let i = 0; i < y; i++){
var z = x[i].index;
this.dataForm.addControl("firstName"+z, new FormControl);
this.dataForm.addControl("lastName"+z, new FormControl);
}
}
//Getting your form data when submitted
onSubmit() {
console.log(this.dataForm.value); //Push the form data into console.log of your browser
}
}
And now in your something.component.html:
<form [formGroup]="dataForm" (ngSubmit)="onSubmit()">
<table class="rtable">
<tr>
<th *ngFor="let column of headings"> <!--Processs the "headings" array in the ts file-->
{{column}}
</th>
</tr>
<tr *ngFor="let row of dataArray">
<td>
{{row.index}}
</td>
<td>
<input id="first-name{{row.index}}" type="text" formControlName="firstName{{row.index}}" value="{{row.fname}}">
</td>
<td>
<input id="last-name{{row.index}}" type="text" formControlName="lastName{{row.index}}" value="{{row.lname}}">
</td>
</tr>
</table>
<button type="submit">Submit</button>
</form>
<p>Form Status: {{ dataForm.status }}</p> <!--Echo form data locally-->>
The information from your database can easily replace the "dataArray". Just update your headings, and add the necessary extra input fields to "dataForm".
Once you are comfortable with that, I would encourage you to look at Angular’s Material for tables.
EDIT
Going forward, should you want to add more fields, you would edit the following (I have used "telNo" as an example):
- Add extra fields to the form in something.component.ts:
generateControls(x: testIntf[]) {
var y = x.length
for (let i = 0; i < y; i++){
var z = x[i].index;
this.dataForm.addControl("firstName"+z, new FormControl);
this.dataForm.addControl("lastName"+z, new FormControl);
this.dataForm.addControl("telNo"+z, new FormControl);
}
}
- Add extra form field in your table in something.component.html:
<td>
<input id="tel-no{{row.index}}" type="text" formControlName="telNo{{row.index}}" value="{{row.telno}}">
</td>
- Obviously your dataArray will also need to be updated to have a "telno" field:
{"index": "1", "fname": "Test", "lname": "One", "telno": "1234587"},
And do not forget to update your interface:
interface testIntf {
index: string,
fname: string,
lname: string,
telno: string,
}
Answered By – Brian
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0