简体   繁体   中英

How can I toggle between mat-checkbox or mat-radio-button in Angular reactive form?

I'm creating a quiz app and need to toggle between mat-checkbox or mat-radio-button, depending on whether the question has one or more answers. Question #1 is a single choice answer question and shows with mat-radio-button whereas Question #2 is a multiple answer question but is also displaying with mat-radio-button instead of mat-checkbox.

This is how my template looks like:

<form [formGroup]="formGroup">
    <ol *ngIf="multipleAnswer === false">
        // using mat-radio-buttons here 
    </ol>
    <ol *ngIf="multipleAnswer === true">
        // using mat-checkboxes here
    </ol>
</form>

and in my ts file the logic looks like:

multipleAnswer: boolean;

ngOnInit() {
  this.multipleAnswer = this.quizService.getQuestionType();
}

ngOnChanges(changes: SimpleChanges) {
  if (changes.question) {
    switch (this.question.type) {
      case 'SINGLE_CHOICE':
        this.formGroup = new FormGroup({
          answer: new FormControl([null, Validators.required])
        });
        break;
      case 'MULTIPLE_CHOICE':
        const multipleChoiceValidator = (control: AbstractControl) =>
          control.value.reduce(
            (valid: boolean, currentValue: boolean) => valid || currentValue
            , false
          ) ? null : {answers: 'At least one answer needs to be checked!'};
        this.formGroup = new FormGroup({
          answers: this.formBuilder.array(this.question.shuffledAnswers
              .map((answer: string) => this.formBuilder.control(false)),
            multipleChoiceValidator
          ),
        });
        break;
    }
  }
}

don't need shuffledAnswers, question type should be inferred from the assets/quiz.ts file (shouldn't need to hard code the question type), and answers should be numbers, not strings

in my QuizService:

getQuestionType(): boolean {
  return (this.correctAnswers && this.correctAnswers.length === 1);
}

There are several problems. First, calling multipleAnswer only inside ngOnInit sets this boolean variable only once at begining, it should be inside ngOnChanges .

But it's not the only issue here, the main problem is in your QuizService . Here you use this.quizService.getQuestionType(); method to set multipleAnswer true or false but inside your getQuestionType() method of QuizService you are checking this.correctAnswers if set and has element length of 1 but this.correctAnswers is always empty when you call it.

Another problem is in your ngOnChanges you have switch (this.question.type) here this.question seems to be undefined evertime.

Edit your code like below and check console outputs everytime a question appears.

Add a new method the get correctAnswers from a question.

getCorrectAnswers(question:QuizQuestion){
   return question.options.filter((item)=> item.correct);
}

And edit begining of ngOnChanges like below, i also added a console output so you can see the data from the new method above.

ngOnChanges(changes: SimpleChanges) {   
   if (changes.question && changes.question.currentValue !== changes.question.firstChange){
     this.currentQuestion = changes.question.currentValue;
     this.correctAnswers = this.getCorrectAnswers(this.currentQuestion);
     this.multipleAnswer = this.correctAnswers.length > 1 ? true : false;
     console.log('correct ans: ', this.correctAnswers);
     ...

I can't modify all of the code since you have your own logic behind your code, but i updated the answer so that variables related to this problem set correctly inside 'ngOnChanges`.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM