Как получить доступ к объекту в наблюдаемом списке - PullRequest
0 голосов
/ 09 октября 2018

Я создаю приложение для викторины.Моя идея - показать 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 голосов
/ 09 октября 2018
.subscribe(arr => {
  arr.forEach(item => {
    console.log(item)
  })      
})

ИЛИ для изменения пунктов:

.subscribe(arr => {
  this.arr = arr.map(item => {
    item.something = 'somevalue'
    console.log(item)
    return item
  })      
})
0 голосов
/ 09 октября 2018

Я предполагаю, что вы хотите иметь весь массив и использовать только определенные элементы в различных ситуациях без необходимости повторной подписки.

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 является асинхронной, поэтому следует помнить, что она будет отображатьсятак, как вы хотите, только после завершения метода подписки.После того, как подписка будет выполнена, она будет обновлена.В таком простом примере вам не нужно сильно беспокоиться об этом.

0 голосов
/ 09 октября 2018

Прежде всего, есть проблема с вашей реализацией:

В вашем ExerciseFlashcardPage вы подписываетесь на Observable, который развернет его.Но тогда вы также используете в своем шаблоне канал async, который будет ожидать Promise или Observable.

Просто удалите строку подписки из своего кода:

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

Вот Образец StackBlitz для вашей ссылки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...