I've been trying for days to get data from input fields inside an Angular Material Table.
I am basically populating a table with values that come from an API, however whenever we don't get any date, in my case a course doesn't have a scheduled date set, i am inserting a text box where the value should be displayed so the user can set a date for that specific course.
Like this:
Note: Sorry for the censoring, work related names had to be removed.
This is my html code:
<mat-card>
<form #traineeForm="ngForm">
<mat-form-field>
<input readonly matInput type="text" name="name" [ngModel] = "trainee.name" #name="ngModel">
</mat-form-field>
<mat-form-field>
<input readonly matInput email type="text" name="email" [ngModel] = "trainee.email" #email="ngModel">
</mat-form-field>
<mat-form-field>
<input readonly matInput type="text" name="type" [ngModel] = "trainee.type" #type="ngModel">
</mat-form-field>
<button mat-raised-button color ="primary" type ="submit">Edit</button>
<button mat-raised-button color ="warn" type ="submit" (click)="onDelete(trainee.id)">Delete</button>
</form>
</mat-card>
<br>
<mat-card>
<table mat-table [dataSource]="courses" class="mat-elevation-z8">
<ng-container matColumnDef="courseOrderID">
<th mat-header-cell *matHeaderCellDef>Course Order ID</th>
<td mat-cell *matCellDef="let element"> {{element.courseOrderID}}</td>
</ng-container>
<ng-container matColumnDef="title">
<th mat-header-cell *matHeaderCellDef>Course Title </th>
<td mat-cell *matCellDef="let element"> {{element.title}}</td>
</ng-container>
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef>Course Description </th>
<td mat-cell *matCellDef="let element"> {{element.description}}</td>
</ng-container>
<ng-container matColumnDef="duration">
<th mat-header-cell *matHeaderCellDef>Duration </th>
<td mat-cell *matCellDef="let element"> {{element.duration}}</td>
</ng-container>
<ng-container matColumnDef="scheduledDate">
<th mat-header-cell *matHeaderCellDef>Scheduled Date </th>
<td mat-cell *matCellDef="let element">
<mat-form-field>
<input matInput [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
{{element.scheduledDate}}</td>
</ng-container>
<ng-container matColumnDef="trainer">
<th mat-header-cell *matHeaderCellDef>Trainer </th>
<td mat-cell *matCellDef="let element">
<mat-form-field><input matInput color="warn" *ngIf="!element.trainer"></mat-form-field> {{element.trainer}}</td>
</ng-container>
<ng-container matColumnDef="save">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let element">
<button mat-raised-button color ="primary" type ="submit" (click)="onSaveAssignment(trainee, element, picker)">Save</button></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="coursesdisplayColumns">
</tr>
<tr mat-row *matRowDef="let courses; columns: coursesdisplayColumns"></tr>
</table>
<br>
</mat-card>
And this is my TypeScript code:
import { Trainee } from '../trainees.model';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { TraineesService } from '../../trainees.service';
import { ActivatedRoute, ParamMap } from '@angular/router';
import { Course } from '../../courses/courses.model';
import { CoursesService } from '../../courses.service';
import { Assignment } from '../../assignments/assignments.model';
import { NgForm } from '@angular/forms';
@Component({
selector: 'app-trainee-details',
templateUrl: './trainee-details.component.html',
styleUrls: ['./trainee-details.component.css']
})
export class TraineeDetailsComponent implements OnInit, OnDestroy {
private traineeId: string;
trainee: Trainee;
assignment: Assignment;
courses: Course[] = [];
coursesdisplayColumns = ['courseOrderID', 'title','description','duration','scheduledDate','trainer','save'];
constructor(public traineeService: TraineesService, public route: ActivatedRoute, public coursesService: CoursesService){}
ngOnInit() {
this.route.paramMap.subscribe((paramMap: ParamMap) => {
if(paramMap.has('traineeId')){
this.traineeId = paramMap.get('traineeId');
this.trainee = this.traineeService.getTrainee(this.traineeId);
}
});
this.coursesService.getCoursesByJob(this.trainee.job);
this.coursesService.getCoursesUpdateListener().subscribe((courses: Course[]) =>{
this.courses = courses;
});
}
onDelete(traineeId: string)
{
this.traineeService.deleteTrainee(traineeId);
}
onSaveAssignment(trainee: Trainee, selectedCourse: Course, dateForm: Date){
console.log(trainee.id);
console.log(selectedCourse.description);
console.log(dateForm);
}
ngOnDestroy() {
}
}
When i call onSaveAssignment(), the trainee ID and course ID are getting logged in the console correctly as those are defined in typescript, but I have no ideea how should i bring that date selected in the interface, i tried with ng-model but it did not work and I had to define a form for each input and still did not work.
Is there any way to get that values from inputs on each row when the Save button is pressed ?
Or if i put 1 button for all of them is there any way to do a foreach on every input value in the interface ?
You can get the values with ngModel by creating an object containing all values using the index as attribute.
In you component, put an object:
public myDates : any = {};
Then use ngModel with the index for your input date:
<ng-container matColumnDef="scheduledDate">
<th mat-header-cell *matHeaderCellDef>Scheduled Date </th>
<td mat-cell *matCellDef="let element; let i = index">
<mat-form-field>
<input matInput [(ngModel)]="myDates[i]" [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
</td>
</ng-container>
For each row, it will add an attribute to the object myDates
. Using index permits to guarantee uniqueness. Your object will look like: {1: date1, 2: date2 ...}
.
Then you can get the value by knowing the index of the row. You can get it directly when clicking on the button:
<ng-container matColumnDef="save">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let element; let i = index">
<button mat-raised-button color ="primary" type ="submit" (click)="onSaveAssignment(trainee, element, myDates[i])">Save</button>
</td>
</ng-container>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With