2017-09-04 6 views
0

目的:私はクイズのコンポーネントを持っていて、テンプレートで一度に1つの質問を表示できるようにしたい。次のボタンをクリックすると、次の質問が表示されます。Observable <any[]>の値を次のクリックまでAngularテンプレートに表示する方法

問題:FirebaseListObservableに質問リスト全体が含まれています。テンプレートに一度に1つだけレンダリングするにはどうすればいいですか?私は今までのコードの下に貼り付けました。リスト全体をレンダリングします。初心者レベルのRxJS知識のおかげで、ここからどこに行くのか分かりません。

import { Component, OnInit } from '@angular/core'; 
import { FirebaseService } from '../../firebase.service'; 
import { Observable } from 'rxjs/Observable'; 
import { Question } from '../../model/question'; 

@Component({ 
    selector: 'app-quiz', 
    template: ` 
    <md-grid-list cols="1" rowHeight="2:1"> 
     <md-grid-tile> 
     <md-card *ngFor="let question of questions$ | async"> 
      <md-card-header> 
      <md-card-title>{{question?.course}}</md-card-title> 
      <md-card-subtitle>{{question?.chapter}}</md-card-subtitle> 
      </md-card-header> 
      <md-card-content> 
      <p>{{question?.question}}</p> 
      </md-card-content> 
      <md-card-actions> 
      <button md-button>See Answer</button> 
      <button (click)="nextQuestion(question)" md-button>Next 
Question</button>    
      </md-card-actions> 
     </md-card> 
     </md-grid-tile> 
    </md-grid-list> 
    `, 
    styles: [`.example-card { width: 400px;}`] 
}) 
export class QuizComponent implements OnInit { 

    questions$: Observable<Question[]>; 

    constructor(private fbDatabase: FirebaseService) { } 

    ngOnInit() { 
    this.questions$ = this.fbDatabase.getFirebaseList('/questions'); 
    } 

    nextQuestion() { 
    } 

} 
+0

はちょうど私の答えを更新しました) 。その場合は私に教えてください – sugarme

答えて

0

これまでの質問を表示したくない場合は、質問配列の各項目(質問オブジェクト)を一度にレンダリングするだけです。 私はビューにレンダリングするために新しいobservable変数型Questionを追加します。配列内の項目を追跡するためのインデックス変数。次のようなもの:

@Component({ 
     selector: 'app-quiz', 
     template: ` 
     <md-grid-list cols="1" rowHeight="2:1"> 
      <md-grid-tile> 
      <md-card *ngIf="question | async"> 
       <md-card-header> 
       <md-card-title>{{(question | async)?.course}}</md-card-title> 
       <md-card-subtitle>{{(question | async)?.chapter}}</md-card-subtitle> 
       </md-card-header> 
       <md-card-content> 
       <p>{{(question | async)?.question}}</p> 
       </md-card-content> 
       <md-card-actions> 
       <button md-button>See Answer</button> 
       <button (click)="nextQuestion(index + 1)" md-button>Next 
    Question</button>    
       </md-card-actions> 
      </md-card> 
      </md-grid-tile> 
     </md-grid-list> 
     `, 
     styles: [`.example-card { width: 400px;}`] 
    }) 

    export class QuizComponent implements OnInit { 

     questions: Array<Question>; 

     question: Observable<Question>; 
     index: number = 0; 

     constructor(private fbDatabase: FirebaseService) { } 

     ngOnInit() { 
      this.fbDatabase.getFirebaseList('/questions').subscribe((res) =>{ 
       if(res) { 
       console.log(res); 
       this.questions = res; 
       this.question = this.nextQuestion(index); 
       } 
      }); 

     } 

     nextQuestion(i: number): Observable<Question> { 
      if i >= this.questions.length { 
      i = 0; 
      } 

      return Observable.of(this.questions[i]); 
     } 

    } 

それがうまくいくかどうか教えてください。その後、AppComponentのコードとそのコメントは私を理解するのに十分なされている

import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core'; 

export interface IQuestion { 
    label: string; 
    answers: string[]; 
} 

@Component({ 
    selector: 'app-question', 
    template: ` 
    <div> 
     <b>Question:</b> 
     <p>{{ question.label }}</p> 

     <b>Possible answers</b> 
     <p *ngFor="let answer of question.answers">{{ answer }}</p>  
    </div> 
    `, 
    styles: [``], 
    changeDetection: ChangeDetectionStrategy.OnPush 
}) 
export class AppQuestionComponent { 
    @Input() question: IQuestion; 
} 

+0

テンプレートは空白ですが、コンソールにエラーはありません。私はnext.Question関数の先頭にconsole.log(this.questions、this.question)を追加し、配列が初期化されていることを確認しましたが、Observableは最初にNextをクリックするまで未定義です。クリック後、私のMDカードはまだ空です。しかし、コンソールはScalar Observableと言う。私が次をクリックし続けると、私は同じ観察可能な状態を維持し続けます。私のリストの最初のもの。 –

+0

@LandonWaldner私はちょうど答えを更新しました。私は 'ngIf'を追加して、ファイルをレンダリングする前にfirebaseからデータを取得し、テンプレート内で' async'を修正しました(もし動作すれば、* ngIfまたはasyncを質問オブジェクトから削除できます。この解決策が機能しない場合は、あなたのデータ構造についてわからないので、console.logの出力を送ってください。 – sugarme

+0

ngOnInit(){ this.index = 0; これはfirebaseから戻ってくるデータを表示するためのconsole.logです。 .fbDatabase.getFirebaseList( '/質問')( (RES)=> { IF(RES){ this.questionsの= RESを、 this.nextQuestion(this.index);} })加入。 } nextQuestion(i:number){ if(i> = this.questions.length){ これです。インデックス= i = 0; } this.question = Observable ofof(this.questions [i]); this.index ++; } –

0

まず第一に、私は質問を表示するには、コンポーネントを作成することにより、コンポーネントパターンを利用すると思います思う:
TSコード

@Component({ 
    selector: 'my-app', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css'] 
}) 
export class AppComponent implements OnInit { 
    question$: Observable<IQuestion>; 
    questions$: Observable<IQuestion[]>; 

    _click$ = new Subject<void>(); 
    click$ = this._click$.startWith(null); 

    constructor(private firebaseService: FirebaseService) { } 

    ngOnInit() { 
    // get the questions from firebase 
    this.questions$ = this 
     .firebaseService 
     .getFirebaseList('your-list') 
     // add a false statement so we know when to ends 
     .map(questions => [...questions, false]); 

    const questionsOneByOne$ = this 
     .questions$ 
     .mergeMap(
     questions => 
      questions.map(
      // explode each question to a different stream value... 
      question => Observable.of(question) 
     ) 
    ) 
     // ...so we can get them one by one 
     .concatAll(); 

    this.question$ = Observable 
     .zip(questionsOneByOne$, this.click$) 
     .map(([question, _]) => question); 
    } 

    nextQuestion() { 
    this._click$.next(); 
    } 
} 

HTMLコード

<div *ngIf="question$ | async as question; else noMoreQuestions"> 
    <app-question [question]="question"></app-question> 

    <button (click)="nextQuestion()">Go to next question</button> 
</div> 

<ng-template #noMoreQuestions> 
    No more questions 
</ng-template> 

ここStackblitz上ライブデモは(嘲笑firebaseリスト付き)
https://stackblitz.com/edit/angular-mbnscx

あなたは、さらに質問(複数可)を持っている場合は、私に教えてくださいます。

関連する問題