如何访问可观察列表中的对象

时间:2018-10-09 12:35:17

标签: angular firebase firebase-realtime-database ionic3

我正在构建测验应用程序。我的想法是每页显示1个问题。如何使用Observable订阅并在列表中获取对象。

代替使用*ngFor来显示我所有的对象。有没有一种方法可以在subscribe块中逐个访问对象。

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
    })

  }
}

这是模板:

<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>

3 个答案:

答案 0 :(得分:1)

首先,您的实现存在问题:

在您的ExerciseFlashcardPage中,您正在订阅Observable,它将解开它。但是,然后您还在模板中使用async管道,因此期望使用PromiseObservable

只需从代码中删除订阅行即可:

// Remove this part
this.questions.subscribe(e => {
  console.log(e); // how to access the data //only returns an array of object
});

这样,您也不必担心在销毁该组件时手动取消订阅。

解决方案:

现在针对您的特定用例,如何处理订阅都无关紧要。您只需要一次显示一个问题。为此,您只需在组件类上保留currentQuestion属性,然后将*ngFor[ngClass]

一起使用

然后,当用户提交一个问题时,您可以将currentQuestion属性增加1。

在代码中,这类似于:

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

}

在模板中:

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

这是您推荐的Sample StackBlitz

答案 1 :(得分:0)

.subscribe(arr => {
  arr.forEach(item => {
    console.log(item)
  })      
})

或更改项目:

.subscribe(arr => {
  this.arr = arr.map(item => {
    item.something = 'somevalue'
    console.log(item)
    return item
  })      
})

答案 2 :(得分:0)

我假设您希望拥有整个数组,并且在各种情况下仅使用特定元素,而无需再次订阅。

question: string;
questionsArray: Array<any>
elementToShow = 0; //whichever element you want to show

this.questions.subscribe(e => {
      questionsArray = e;
    });

使用html:

<ion-list>
    <ion-item>
      {{questionsArray[elementToShow]}}

    </ion-item>
</ion-list>

如果您确实要预订数组的一个元素,它将看起来像这样:

question: string;
elementToShow = 0; //whichever element you want to show

this.questions.subscribe(e => {
      question = e[elementToShow];
    }

使用html:

<ion-list>
    <ion-item>
      {{question}}

    </ion-item>
</ion-list>

订阅Observables是异步的,因此请注意,只有在subscription方法结束后,它才会以您想要的方式显示。执行订阅后,将对其进行更新。在这样一个简单的示例中,您不必为此担心很多。