目标:我有一个测验组件,我希望能够在我的模板中一次显示一个问题。用户单击“下一步”按钮时可以显示下一个问题。
问题:我有一个包含整个问题列表的FirebaseListObservable。如何一次只渲染一个模板。到目前为止,我粘贴到了我的代码之下。它呈现整个列表。我不知道从哪里开始,部分原因在于我初学者的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 :(得分:1)
首先,我通过创建一个显示一个问题的组件来利用组件模式:
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;
}
然后,AppComponent
的代码及其评论足以理解我认为:
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上的现场演示(带有模拟的火力列表)
https://stackblitz.com/edit/angular-mbnscx
如果您有其他问题,请告诉我们;)
答案 1 :(得分:0)
如果您不想显示以前的问题,则应该一次渲染问题数组的每个项目(问题对象)。 我将添加一个新的可观察变量类型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]);
}
}
请告诉我这是否适合您?