0

I am trying to display a list a question and when the user clicks submit, the next question would be displayed. For now, I am able to display all the questions on a page. I tried using a flag like other posts suggest but to no success. How would I go about this? This is the appropriate working code without the flag.

<div class="card" *ngIf="!isLoading">
  <div class="card-block text-md-center" *ngFor="let question of questions">
    <form>
      <fieldset class="form-group">
        <h1>{{question.name}}</h1>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios1" value="option1"
               checked>
            {{question.a_Answer}}
          </label>
        </div>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios2" value="option2">
            {{question.b_Answer}}
          </label>
        </div>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios3" value="option3">
            {{question.c_Answer}}
          </label>
        </div>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios4" value="option4">
            {{question.d_Answer}}
          </label>
        </div>
      </fieldset>
      <button type="submit" class="btn btn-primary">Submit</button>
    </form>
  </div>
</div>

This is the code I tried with by hiding the questions based on indexed. It display one question but does not go to the next one when submit is clicked.

<div class="card" *ngIf="!isLoading">
  <div class="card-block text-md-center" *ngFor="let question of questions; let i=index">
    <form [hidden]="currentQuestionNumber !== i">
      <fieldset class="form-group">
        <h1>{{question.name}}</h1>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios1" value="option1"
               checked>
            {{question.a_Answer}}
          </label>
        </div>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios2" value="option2">
            {{question.b_Answer}}
          </label>
        </div>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios3" value="option3">
            {{question.c_Answer}}
          </label>
        </div>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios4" value="option4">
            {{question.d_Answer}}
          </label>
        </div>
      </fieldset>
      <button type="submit" class="btn btn-primary" onclick="setGoToNextTrue()">Submit</button>
    </form>
    </div>
  </div>
</div>

Any help or pointers would be appreciated, thanks!

Component.ts file

import { Component, OnInit } from '@angular/core';
import { Http } from '@angular/http';
import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
import { ToastComponent } from '../shared/toast/toast.component';
import { DataService } from '../services/data.service';

@Component({
  selector: 'app-student',
  templateUrl: './student.component.html',
  styleUrls: ['./student.component.css']
})
export class StudentComponent implements OnInit {

  questions = [];
  isLoading = true;

  currentQuestionNumber;

  question = {};

  addQuestionForm: FormGroup;
  name = new FormControl('', Validators.required);
  a_Answer = new FormControl('', Validators.required);
  b_Answer = new FormControl('', Validators.required);
  c_Answer = new FormControl('', Validators.required);
  d_Answer = new FormControl('', Validators.required);

  constructor(private http: Http,
              private dataService: DataService,
              public toast: ToastComponent,
              private formBuilder: FormBuilder)
  {
    this.currentQuestionNumber = 0;
  }

  ngOnInit() {
    this.getQuestions();
    //this.currentQuestionNumber = 0;

    this.addQuestionForm = this.formBuilder.group({
      name: this.name,
      a_Answer: this.a_Answer,
      b_Answer: this.b_Answer,
      c_Answer: this.c_Answer,
      d_Answer: this.d_Answer
    });
  }

  getQuestions() {
    this.dataService.getQuestions().subscribe(
      data => this.questions = data,
      error => console.log(error),
      () => this.isLoading = false
    );
  }

  setGoToNextTrue()
  {
    this.currentQuestionNumber++;
  }

}

Attempt#2

component.html

<div class="card" *ngIf="isLoading">
  <h4 class="card-header">Loading...</h4>
  <div class="card-block text-xs-center">
    <i class="fa fa-circle-o-notch fa-spin fa-3x"></i>
  </div>
</div>

<div class="card" *ngIf="!isLoading">
  <div class="card-block text-md-center">
    <form (ngSubmit)="onSubmit()">
      <fieldset class="form-group hide" *ngFor="let question of questions;let i=index" [class.show]="i == questionIndex">
        <h1>{{question.name}}</h1>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios1" value="option1"
               checked>
            {{question.a_Answer}}
          </label>
        </div>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios2" value="option2">
            {{question.b_Answer}}
          </label>
        </div>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios3" value="option3">
            {{question.c_Answer}}
          </label>
        </div>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios4" value="option4">
            {{question.d_Answer}}
          </label>
        </div>
      </fieldset>
      <p *ngIf="questionIndex == (questions.length - 1)">This is the last one.</p>
      <button type="submit" class="btn btn-primary" onclick="setGoToNextTrue">Submit</button>
    </form>
  </div>
</div>

component.ts

import { Component, OnInit } from '@angular/core';
import { Http } from '@angular/http';
import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
import { ToastComponent } from '../shared/toast/toast.component';
import { DataService } from '../services/data.service';

@Component({
  selector: 'app-student',
  templateUrl: './student.component.html',
  styleUrls: ['./student.component.css']
})
export class StudentComponent implements OnInit {

  questions = [];
  isLoading = true;

  //currentQuestionNumber;
  questionIndex = 0;

  question = {};

  addQuestionForm: FormGroup;
  name = new FormControl('', Validators.required);
  a_Answer = new FormControl('', Validators.required);
  b_Answer = new FormControl('', Validators.required);
  c_Answer = new FormControl('', Validators.required);
  d_Answer = new FormControl('', Validators.required);

  constructor(private http: Http,
              private dataService: DataService,
              public toast: ToastComponent,
              private formBuilder: FormBuilder)
  {
  }

  ngOnInit() {
    this.getQuestions();
    //this.currentQuestionNumber = 0;
    for(let i = 1; i < 4; i++) {
      this.addQuestionForm = this.formBuilder.group({
        name: this.name,
        a_Answer: this.a_Answer,
        b_Answer: this.b_Answer,
        c_Answer: this.c_Answer,
        d_Answer: this.d_Answer
      });
    }

    this.isLoading = false;

  }

  getQuestions() {
    this.dataService.getQuestions().subscribe(
      data => this.questions = data,
      error => console.log(error),
      () => this.isLoading = false
    );
  }

  private onSubmit() {
    if(this.questionIndex < (this.questions.length - 1)) {
      this.questionIndex++;
    }
  }


}

2 Answers 2

1

You can push one question to the array when submit button clicked or use the index to hide some questions. There is a demo https://embed.plnkr.co/lc6GBFzcjS2Ly0z5QXZT/

Sign up to request clarification or add additional context in comments.

9 Comments

Although your solution does add a question at a time, I would like that only one question is displayed at a time instead of being added on top of the previous one
That's exactly what I need! However, I tried running it and it didn't work. It simply displays all the questions. I added my attempt to the main thread. Let me know what I did wrong. Thanks!
You missed hide class in <fieldset class="form-group **hide**">
Just added it and corrected it in the update, yet it still just shows all questions. I don't have any questions.push in my component.ts file, could that be the issue?
|
0

You can use the [hidden] directive in your template for each form. When generating the template each form will be associated to the index of the question in your questions array. You will need to declare a property in you code behind which will declare the current displayed question.

constructor (){
   this.currentQuestionNumber = 0;
}
setGoToNextTrue(){
  this.currentQuestionNumber++;
  //Other stuff.. for exmaple checking that you've reach the last question
}

In the constructor, By default you can decide to display the first question in the array. Then your template would look like :

<div class="card" *ngIf="!isLoading">
  <div class="card-block text-md-center" *ngFor="let question of questions;let i=index">
    <div *ngIf ="nextQuestion">
    <form [hidden]="currentQuestionNumber !== i">
      <fieldset class="form-group">
        <h1>{{question.name}}</h1>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios1" value="option1"
               checked>
            {{question.a_Answer}}
          </label>
        </div>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios2" value="option2">
            {{question.b_Answer}}
          </label>
        </div>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios3" value="option3">
            {{question.c_Answer}}
          </label>
        </div>
        <div class="form-check">
          <label class="form-check-label">
            <input type="radio" class="form-check-input" name="optionsRadios" id="optionsRadios4" value="option4">
            {{question.d_Answer}}
          </label>
        </div>
        {{setGoToNextFalse()}}
      </fieldset>
      <button type="submit" class="btn btn-primary" onclick="setGoToNextTrue()">Submit</button>
    </form>
    </div>
  </div>
</div>

3 Comments

I added [hidden]="currentQuestionNumber !== i" in the <form>, I added currentQuestionNumber; in the OnInit, then added this.currentQuestionNumber = 0; in the constructor and then added this.currentQuestionNumber++; in the setGoToNextTrue(). When I run the code, only one question appears on the page. However, nothing happens when I click Submit. Am I missing something? I updated the initial thread to include the component.ts file.
Do you want to show one question at a time, or show a new question everytime you submit a form? you can either use currentQuestionNumber !== i which displays one question at a time or currentQuestionNumber < i which will keep the previous questions displayed as you submit them. You can also display {{currentQuestionNumber}} and "hidden" = {{currentQuestionNumber !== i}} to debug what's happening as you click on submit
the issue was that currentQuestionNumber wasn't working because in my component.ts, the isLoading = false was inside the subscribe and not outside. Once I moved it to outside, everything worked like a charm!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.