引言
在【Angular2】ExamPaper组件设计 中说到ExamPaper组件作为各种题型组件的容器,用于选择和传递数据
目前设计的题型组件有5个,可以适应12种题型,分别为radio、sub-radio、input、checkBox、textarea,具体实现都类似,那么就以最常用的radio组件来说明
功能要求
1.根据数据的类型渲染显示数据;
2.提交用户的填入的数据;
3.将用户的数据回显在原来的位置;
代码说明
html code
<p>{{question.questionMainOrder + ". " + question.questionContent}}</p> <div *ngFor="let option of question.questionSubList;let i=index"> <div *ngIf="question.studentAnswerArray"> <input type="radio" name="{{option.questionMainId}}" value="{{option.optionsContent}}" checked="{{option.optionsContent==question.studentAnswerArray[0] ? 'checked' : ''}}" (click)="updateAnswer($event.target,$event.target.value)"> {{alphabet[i]}}{{'. '+option.optionsContent}} </div> <div *ngIf="!question.studentAnswerArray"> <input type="radio" name="{{option.questionMainId}}" value="{{option.optionsContent}}" (click)="updateAnswer($event.target,$event.target.value)"> {{alphabet[i]}}{{'. '+option.optionsContent}} </div> </div>
html 说明
这里把题目id存到了每道题的name中,因为在设计AnswerSheet组件的时候把题目id已经用到了id上了,所以这里只好放在name中,其实应该调换一下,不过改动量比较大,而且当前也能实现;
通过两个ngIf来判断返回的题目中是否有用户答案,如果有则显示;
这里的用户采用数组的形式,无论选择,多选,还是填空,都是数组,因为一道题的答案可能有多个,需要渲染在相应的位置,所以答案之间必须是分开的,采用数组形式就可以解决;
ts code
@Input() question: QuestionMainModel; //题干实体
@Input() paperId: string; //试卷ID
@Input() questionTypeId: string; //题型ID
@Output() updatedAnswer = new EventEmitter<Answer>();
alphabet = Alphabet;
done: boolean = false;
updateAnswer(el: Element,value: string) {
//用户的答案(在方法内声明,每次提交为新答案实体,simplechange才会识别)
let answer: Answer = new Answer;
//声明数组
answer.studentAnswerArray = [];
//获得题目id
let questionid: string = el.getAttribute("name");
//处理用户答案
answer.studentId = localStorage.getItem("userId");
answer.paperId = this.paperId;
answer.questionTypeId = this.questionTypeId;
answer.questionMainId = questionid;
answer.studentAnswerArray[0] = value;
answer.done = true;
console.log("question-radio-answer--" + answer);
//传递用户的答案
this.updatedAnswer.emit(answer);
this.updateStudentAnswerToBackend(answer);
}
/* 向后台提交学生答案 */
public updateStudentAnswerToBackend(answer: Answer) {
let url: string = "examinationEvaluation-web/onlineExam/updatePaperRecordByRecord" + this.authGuardService.getTicket();
let body: string = JSON.stringify(answer);
this.exampapaerservice.post(url,body).subscribe(
res => {
if (res.json().data != true) {
let ns: number = parseInt(localStorage.getItem("NetWorkState"));
ns = ns + 1;
localStorage.setItem("NetWorkState",ns.toString());
}
}
);
}
ts 说明
在实时提交答案的过程中,每次必须是new一个新的实体,不然AnswerSheet中SimpleChange无法监测到;
同时向后端提交答案的时候,需要对返回值进行判断,如果提交失败则修改localstorage中的NetWorkState值,在Information组件中timer会每秒读取这个值,来监测网络状态;
小结
Question组件中的5个题型组件的逻辑是类似的,只是实现方式不太一样;
关于input题型组件很简单,就不加赘述;
checkBox题型组件涉及的难点在 【Angular2】CheckBox获取值的两种方式 中已说明;
textarea题型组件涉及到的难点在格式的保存与显示,在【Angular2】简易版富文本编辑器 和 【Angular2】通过Pipe使用InnerHTML 已经说明