【发布时间】:2020-05-28 18:31:08
【问题描述】:
我正在尝试使用 Angular 8 为一门课程开发一个数字评分系统。实际情况非常复杂,因此我将部分分开并创建了一个新项目来解释我的问题所在。如果您查看图像,您将了解我正在努力完成的工作。假设这是一门课程的成绩表。对于一门课程,可以有不同的考试。注册本课程的学生,他们将参加本课程的特定考试,然后教师将使用此表格提交编号。假设,对于第一行第一列(期中考试),表格不应允许您提供超过 25 分或小于零的分数。如果您在 Mid Exam 字段中输入 20,那么 Total 将显示 20,GP 将显示 0.00,Grade 将显示 F。然后如果您在 Final Exam 字段中输入 30,总值将更新为 50,GP 将更新到 0.00 并将更新为 F。再次,如果您在评估字段中输入 40,总值将更新为 90,GP 将更新为 4.00 并将更新为 A。所有行都会发生同样的事情.如果您单击“保存”按钮,将提交数字。
现在我正在描述我尝试过的代码和我的问题,这里studentList、examList 和gradePointList 数组将从后端服务填充课程的数据。我创建了populateSomeDemoData 方法来生成这些数据。 studentList 是 Student 对象的数组,其中包含学生的 id 和名称。 ExamList 是一个考试对象数组,其中包含考试 ID、考试名称和该考试的总分。 gradePointList 包含字母等级和等级点数的范围。假设总分在 90(最小数字)和 100(最大数字)之间,则成绩为 4.00,字母成绩为 A。我尝试创建一个表单 gradeForm 并在examList 上为每行应用一个循环来创建输入场地。但为此,我无法使用表单控件访问特定字段,这就是为什么我未能计算连续的总分和成绩点的原因。同样出于同样的原因,我未能创建将发送到后端的 Grade 对象列表。 Grade 是每个字段的对象,将包含学生、考试和编号。如果一个字段被更新,这个成绩对象也将被更新。如果保存按钮触发,这个号码列表将被传递到后端。
HTML 部分是:
<form [formGroup]="gradeForm" (ngSubmit)="saveGrade()">
<table>
<thead>
<tr>
<th> #</th>
<th>Student</th>
<th *ngFor="let exam of examList">{{exam.name}} ({{exam.marks}}%)</th>
<th>Total</th>
<th>GP</th>
<th>Grade</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let student of studentList; let i = index">
<th> {{ i + 1 }} </th>
<th> {{ student.id }} <br/> {{student.name}} </th>
<th *ngFor="let grade of gradeFields.controls; let j = index" formArrayName="gradeFields">
<input type="number" [formControlName]="j">
</th>
<th>??</th>
<th>??</th>
<th>??</th>
</tr>
</tbody>
</table>
<div class="wrapper">
<button class="button">Save Grade</button>
</div>
</form>
TypeScript 部分是:
export class AppComponent {
public gradeForm: FormGroup;
// This arrays will populate dynamically from the database
public examList: Exam[] = [];
public studentList: Student[] = [];
public gradePointList: GradePoint[] = [];
public gradeList: Grade[] = [];
constructor(private formBuilder: FormBuilder) {
this.populateSomeDemoData();
this.createGradeForm();
}
createGradeForm(): void {
this.gradeForm = this.formBuilder.group({
gradeFields: this.formBuilder.array([
this.formBuilder.control('')
])
});
for (let i = 0; i < this.examList.length - 1; i++) {
this.gradeFields.push(this.formBuilder.control(''));
}
}
get gradeFields() {
return this.gradeForm.get('gradeFields') as FormArray;
}
saveGrade(): void {
console.log(this.gradeForm.get('gradeFields').value);
console.log(this.gradeList);
console.log('Grade List Saved');
}
populateSomeDemoData(): void {
// Static value for populating arrays for easy explanation
const midTerm = new Exam();
midTerm.id = '1';
midTerm.name = 'Mid Exam';
midTerm.marks = 25;
const finalExam = new Exam();
finalExam.id = '2';
finalExam.name = 'Final Exam';
finalExam.marks = 30;
const assessmentExam = new Exam();
assessmentExam.id = '3';
assessmentExam.name = 'Assessment';
assessmentExam.marks = 40;
const attendance = new Exam();
attendance.id = '4';
attendance.name = 'Attendance';
attendance.marks = 5;
this.examList.push(midTerm);
this.examList.push(finalExam);
this.examList.push(assessmentExam);
this.examList.push(attendance);
// Static value for populating arrays for easy explanation
const student1 = new Student();
student1.id = '14101561';
student1.name = 'Petey Cruiser';
const student2 = new Student();
student2.id = '14112201';
student2.name = 'Bob Frapples';
const student3 = new Student();
student3.id = '14112202';
student3.name = 'Paul Molive';
const student4 = new Student();
student4.id = '16113004';
student4.name = 'Anna Mull';
const student5 = new Student();
student5.id = '16113005';
student5.name = 'Gail Forcewind';
this.studentList.push(student1);
this.studentList.push(student2);
this.studentList.push(student3);
this.studentList.push(student4);
this.studentList.push(student5);
// Static value for populating arrays for easy explanation
const aGradePoint = new GradePoint();
aGradePoint.minimumNumber = 90;
aGradePoint.maximumNumber = 100;
aGradePoint.gradePoint = 4;
aGradePoint.letterGrade = 'A';
const bGradePoint = new GradePoint();
bGradePoint.minimumNumber = 80;
bGradePoint.maximumNumber = 89;
bGradePoint.gradePoint = 3.5;
bGradePoint.letterGrade = 'B';
const cGradePoint = new GradePoint();
cGradePoint.minimumNumber = 70;
cGradePoint.maximumNumber = 79;
cGradePoint.gradePoint = 3;
cGradePoint.letterGrade = 'C';
const dGradePoint = new GradePoint();
dGradePoint.minimumNumber = 60;
dGradePoint.maximumNumber = 69;
dGradePoint.gradePoint = 2.5;
dGradePoint.letterGrade = 'D';
const fGradePoint = new GradePoint();
fGradePoint.minimumNumber = 0;
fGradePoint.maximumNumber = 59;
fGradePoint.gradePoint = 0;
fGradePoint.letterGrade = 'F';
this.gradePointList.push(aGradePoint);
this.gradePointList.push(bGradePoint);
this.gradePointList.push(cGradePoint);
this.gradePointList.push(dGradePoint);
this.gradePointList.push(fGradePoint);
}
}
export class Student {
public id: string;
public name: string;
constructor(student?) {
student = student || {};
this.id = student.id || null;
this.name = student.name || null;
}
}
export class Exam {
public id: string;
public name: string;
public marks: number;
constructor(exam?) {
exam = exam || {};
this.id = exam.id || null;
this.name = exam.name || null;
this.marks = exam.marks || 0;
}
}
export class GradePoint {
public minimumNumber: number;
public maximumNumber: number;
public gradePoint: number;
public letterGrade: string;
constructor(gradePoint?) {
gradePoint = gradePoint || {};
this.minimumNumber = gradePoint.minimumNumber || 0;
this.maximumNumber = gradePoint.maximumNumber || 59;
this.gradePoint = gradePoint.gradePoint || 0;
this.letterGrade = gradePoint.letterGrade || 'F';
}
}
export class Grade {
public student: Student;
public exam: Exam;
public number: number;
constructor(grade?) {
grade = grade || {};
this.student = grade.student || null;
this.exam = grade.exam || null;
this.number = grade.number || null;
}
}
为了更好地理解代码,我创建了一个 StackBlitz。请点击此链接查看代码。 Click here
我看到了很多与表单数组相关的帖子,但我的情况完全不同。在这里,我没有任何添加按钮来推送数组或计算值。并且所有情况都有固定的形式。但在我的例子中,数组也将从列表中生成,因为examList 是动态的。
我认为我在表单上创建时遇到了问题,或者我的方法是错误的。请帮助我完成我的目标,生成总分并创建成绩单。将不胜感激。提前致谢。
【问题讨论】:
-
这个场景需要用到嵌套数组,我看你的成绩字段是数组,应该是嵌套数组。
-
也许没有。我看过很多帖子,表单数组有很多这样的例子,但我的情况完全不同。在这里,我没有任何添加按钮来推送数组或计算值。所有情况都有固定的表格,就像你提到的那个链接一样,“项目名称”是固定的。但就我而言,数组也将从列表中生成,因为examList 是动态的。
-
您是否意识到您的 getFields 数组长度是 4 而应该是 16 ?这不是敲钟吗?您每次都在循环并使用索引作为 formControl 的名称。
-
是的,我明白了。但我不明白如何为这 20 个字段创建表单字段并动态获取表单字段值。你能帮帮我吗?
标签: angular typescript angular-reactive-forms angular-forms