Search code examples
angulartypescriptfirebasengmodel

Angular - Selected option not being captured in ngForm object


Edited to remove irrelevant code.

I am trying to print the form object to the console but the selected option is not being displayed. It is showing as undefined in console.

enter image description here

I have put the codes below. If somebody can guide on what is wrong with this particular code it would be helpful. Let me know if any additional information is required.

Component.html:

<form #f="ngForm" (ngSubmit)="save(f.value)">

....

  <div class="form-group">
    <label for="category">Category</label>
    <select ngModel name="category" id="category" class="form-control">
      <option value=""></option>
      <option *ngFor="let c of categories$ | async" [value]="c.key">
        {{ c.name }}
      </option>
    </select>
  </div>

....

Component.ts:

import { CategoryService } from './../../category.service';

....

export class ProductFormComponent implements OnInit {

  categories$;

  constructor(categoryService: CategoryService) {
    this.categories$ = categoryService.getCategories();
  }

  save(product) {
    console.log(product);
  }

....

Category.Service.ts:

import { AngularFireDatabase } from 'angularfire2/database';

....

  getCategories() {
    return this.db
      .list('/categories', ref => ref.orderByChild('name'))
      .valueChanges();
  }

....

I want to get the value highlighted from the Firebase database to be captured in the object. If I put c.name I am getting the user friendly name.

Firebase database structure.


Solution

  • I found the answer on the below link. Instead of .valueChanges() we should be using .snapshotChanges() since the former returns an Observable without any metadata.

    Upgrading to AngularFire 5.0

    The updated files with the changes are given below.

    Category.service.ts: Changed valueChanges() to snapshotChanges().

    import { AngularFireDatabase } from 'angularfire2/database';
    
    ....
    
      getCategories() {
        return this.db
          .list('/categories', ref => ref.orderByChild('name'))
          .snapshotChanges();
      }
    
    ....
    

    Component.html: In the select option interpolation, changed c.name to c.payload.val().name.

    <form #f="ngForm" (ngSubmit)="save(f.value)">
    
    ....
    
      <div class="form-group">
        <label for="category">Category</label>
        <select ngModel name="category" id="category" class="form-control">
          <option value="blank"></option>
          <option *ngFor="let c of categories$ | async" [value]="c.key">
            {{ c.payload.val().name }}
          </option>
        </select>
      </div>
    
    ....