DEV
DEV

Reputation: 949

Passing data from service to angular components

I am reading data from a firebase database and creating some objects based on the data received and pushing the data into a list. But the control goes back to the component before the objects are created or pushed into the list. I am confused to use any life cycle hooks in this approach.

Class Service(){

questions: QuestionsData<any>[]=[];

getQuestions(FormKey: string) {

var dbQuestions = this.af.list('/elements', {
   query: {
  limitToLast: 200,
  orderByChild: 'formid',
  equalTo: FormKey
 }
})

  dbQuestions.subscribe(snapshots=>{
  snapshots.forEach(elementData => {
  this.questions.push(new TextboxQuestion({
    key: elementData.elementname,
    label: elementData.displaytext,
    value: elementData.elementvalue,
    required: false,
    order: elementData.sortorder
  }))
 }
}
}

Can anyone suggest how to consume this data in my component.

Upvotes: 1

Views: 1211

Answers (2)

Carlos Ferras
Carlos Ferras

Reputation: 314

Your service should be more or less like this:

import 'rxjs/add/operator/map'

Class Service() {

    getQuestions(FormKey: string): Observable<QuestionsData<any>[]>  {

        return dbQuestions = this.af.list('/elements', {
            query: {
                limitToLast: 200,
                orderByChild: 'formid',
                equalTo: FormKey
            }
        }).map(snapshots=>{
            conts questions: QuestionsData<any>[]=[];

            snapshots.forEach(elementData => {
                questions.push(new TextboxQuestion({
                    key: elementData.elementname,
                    label: elementData.displaytext,
                    value: elementData.elementvalue,
                    required: false,
                    order: elementData.sortorder
                }))
            })

            return questions;
        })
    }
}

And in the component:

serviceInstance.getQuestions(FormKey).subscribe(questions => {
    // your code here
})

Upvotes: 1

vince
vince

Reputation: 8306

As JB Nizet mentioned in the comments, you should not subscribe to the observable and unwrap it in your template as you are currently doing. Angular provides the async pipe to handle that subscription for you. You simply want to map your data to TextBoxQuestion's. You can do that with the following code.

class MyComponent {

  questions$: QuestionsData<any>[]=[];

  getQuestions(FormKey: string) {

    const dbQuestions$ = this.af.list('/elements', {
      query: {
        limitToLast: 200,
        orderByChild: 'formid',
        equalTo: FormKey
      }
    });

    this.questions$ = dbQuestions$.map(snapshots => 
      snapshots.map(data => new TextBoxQuestion({
         key: data.elementname,
         // and so on...
      });
  }
}

If you want to run that when your component initializes, use the OnInit lifecycle hook:

ngOnInit() {
  this.getQuestions(/* form key */);
}

And then use the async pipe in your template like this:

<ul>
  <li *ngFor="let question of questions$ | async">
    {{ question.key }}
  </li>
</ul>

Upvotes: 2

Related Questions