问题
I'm building a quiz app. My idea is to show 1 question per page. How do I subscribe and get an object inside a list using Observable.
Instead of using *ngFor
which display all of my objects. Is there a way to access the object one by one inside the subscribe
block.
export class ExerciseFlashcardPage {
questions: Observable < any > ;
type: string;
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public afd: AngularFireDatabase
) {
this.type = this.navParams.get('data');
this.questions = this.afd.list('exercises/' + this.type).valueChanges();
this.questions.subscribe(e => {
console.log(e); // how to access the data //only returns an array of object
})
}
}
And here's the Template:
<ion-header>
<ion-navbar>
<ion-title>exercise-flashcard</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-list>
<ion-item *ngFor="let item of questions | async">
{{item.question}}
</ion-item>
</ion-list>
</ion-content>
回答1:
First up, there's an issue with your implementation:
In your ExerciseFlashcardPage
, you're subscribing to the Observable
which will unwrap it. But then you're also using the async
pipe in your template which will be expecting a Promise
or an Observable
.
Just remove the subscription line from your code:
// Remove this part
this.questions.subscribe(e => {
console.log(e); // how to access the data //only returns an array of object
});
That way you also won't have to worry about manually unsubscribing from the subscription when this component is destroyed.
SOLUTION:
Now for your specific use-case, it doesn't matter how you handle the subscription. All you need is to show one question at a time. For that, you can just keep a currentQuestion
property on your Component Class and then use *ngFor
along with [ngClass]
And then when the user submits one question, you can increment the currentQuestion
property by 1.
In code, this would look something like:
import { map } from 'rxjs/operators';
export class ExerciseFlashcardPage {
questions: Observable < any > ;
type: string;
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public afd: AngularFireDatabase
) { }
ngOnInit() {
this.type = this.navParams.get('data');
this.questions = this.afd.list('exercises/' + this.type).valueChanges()
// The below Pipe operation is not required if you don't plan to change the data-model of the question object.
.pipe(map(questions => {
return questions.map(question => {
return {
...question,
yourNewKeyHere: 'Value to that new key here'
}
});
}));
}
submitCurrentQuestion() {
// Make changes to save the answer
++this.currentQuestion;
}
}
And in template:
<ion-header>
<ion-navbar>
<ion-title>exercise-flashcard</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-list>
<ion-item
*ngFor="let item of questions | async; let i = index;"
[ngClass]="(i === currentQuestion) ? '': 'hide'">
{{item.question}}
</ion-item>
</ion-list>
</ion-content>
CSS:
.hide {
display: none;
}
Here's a Sample StackBlitz for your ref.
回答2:
.subscribe(arr => {
arr.forEach(item => {
console.log(item)
})
})
OR to change the items:
.subscribe(arr => {
this.arr = arr.map(item => {
item.something = 'somevalue'
console.log(item)
return item
})
})
回答3:
I assume you want to have the whole array and use only specific elements in various situations without having to subscribe again.
question: string;
questionsArray: Array<any>
elementToShow = 0; //whichever element you want to show
this.questions.subscribe(e => {
questionsArray = e;
});
With html:
<ion-list>
<ion-item>
{{questionsArray[elementToShow]}}
</ion-item>
</ion-list>
If you really want to subscribe to one element of the array it would look like this:
question: string;
elementToShow = 0; //whichever element you want to show
this.questions.subscribe(e => {
question = e[elementToShow];
}
With html:
<ion-list>
<ion-item>
{{question}}
</ion-item>
</ion-list>
Subscribing to Observables is async, so be aware that it will be displayed in the way you want only after the subscribe method ends. After subscribe is executed it will be updated. In such a simple example you dont have to worry much about this.
来源:https://stackoverflow.com/questions/52721230/how-to-access-the-object-in-the-observable-list