Displaying list one by one in angular2

2019-09-19 02:46发布

问题:

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++;
    }
  }


}

回答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/



回答2:

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>