Search code examples
angularjsangularrxjsangular4-forms

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.


Solution

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