【问题标题】:Getting data from AngularFirestore from HTML to the TypeScript从 AngularFirestore 获取数据从 HTML 到 TypeScript
【发布时间】:2018-11-04 09:23:33
【问题描述】:

这是我的第一个 Angular-Firestore 项目。我想要做的是从我使用 *ngFor 插入到数据列表的 HTML 页面中获取数据。当我按下表单上的提交按钮时。有些数据必须由用户输入,有些来自 *ngFor 循环。问题是它引发以下错误:SellinglistComponent.html:53 错误错误:使用无效数据调用函数 DocumentReference.set()。不支持的字段值:未定义(在字段 ownerID 中找到)

但是当我再次按下提交按钮(按下两次)时,它没有问题,我可以看到数据正在发送到数据库。这会是什么情况?请帮我解决它。谢谢。

TypeScript 文件如下

import { Component, OnInit, Input } from '@angular/core';
import { PaginationService } from '../pagination.service';
import { AngularFirestore, AngularFirestoreDocument } from 'angularfire2/firestore';
import * as firebase from 'firebase/app';

@Component({
  selector: 'app-sellinglist',
  templateUrl: './sellinglist.component.html',
  styleUrls: ['./sellinglist.component.scss']
})

export class SellinglistComponent implements OnInit 
{
  bidObjectId : string;
  panelOpenState = false;
  public show: boolean;
  public bidName : any;
  bidPrice : number;
  bidAmount : number;
  userRef: AngularFirestoreDocument<{}>;
  ownerID : any;

  constructor(public page1: PaginationService, private db: AngularFirestore) {}

  public openDialog(): void 
  {
    this.show = !this.show;
  }

  ngOnInit() 
  { 
    //iterate through all the saleCrop object using pagination service for more info, refer pagination service component
    this.show = false;
    this.page1.init('saleCrops','postDate', { reverse: true, prepend: false});
    var user = firebase.auth().currentUser;
    var userID = user.uid;
    this.userRef = this.db.doc('users/'+userID);
    this.userRef.ref.get()
    .then((doc) => {
      //checks if the user is logged in and copies their first and last names to the a varible to be used later in the DB
      if(doc.exists) {
        console.log("hello")
        this.bidName = doc.data().fname+" "+doc.data().lname;
      }
      else{
        console.error("No user logged in!");
      }
    })
    console.log(this.bidName)
    
  }

  //Handling the infinite scroll in the marketplace 
  scrollHandler(e) 
  {
    if (e === 'bottom') {
      this.page1.paginate('backward');
    }
  }

  addBid(bidObj)
  {  
    this.bidObjectId = bidObj;
    console.log(bidObj)
    this.db.collection('saleCrops').doc(this.bidObjectId).ref.get()
    .then((doc) => {
      if (doc.exists) {
        console.log(doc.data())
        this.ownerID = doc.data().posterID;
        console.log(1)
        console.log(this.ownerID)
        console.log(2)
      }
      else{
        console.log("error");
      }
    });
    this.db.collection("bids").add({
      bidderName : this.bidName,
      accepted : false,
      bidPrice : this.bidPrice,
      bidAmount : this.bidAmount,
      bidDate : new Date(),
      bidderID : this.userRef.ref,
      objectID : this.bidObjectId,
      ownerID : this.ownerID,
    })
    .then(function() {
      console.log("Bid added Successfully");
    })
    .catch(function(error) {
      console.error("Error Doc: ", error);
    });
  }
}

HTML文件如下

<mat-card *ngFor="let saleCrops of page1.data | async">
  <div class="row">
    <div class="example-small-box">
        <img src="{{ saleCrops.photoURL }}" style="object-fit: cover; height: 150px; width: 150px; border-radius: 50%">
    </div>
    <div class="example-small-box">
        <h2 class="">
          <br>
          {{ saleCrops.itemName }}<br/><font size="5">{{ saleCrops.itemAmount }}kg</font><br/><small>Rs. {{ saleCrops.unitPrice }} per 1kg</small>
        </h2>
    </div>
  </div>
    <mat-accordion>
      <mat-expansion-panel (opened)="panelOpenState = true"
      (closed)="panelOpenState = false">
        <mat-expansion-panel-header>
          <mat-panel-title></mat-panel-title>
          <mat-panel-description>
            Click For More Details
          </mat-panel-description>
        </mat-expansion-panel-header>
        <div class="row">
          <div class="example-very-small-box">
            <strong style="font-size: medium">Poster Details</strong> 
            <br><strong>Name</strong> : {{ saleCrops.posterName }}
            <br><strong>Region</strong> : {{ saleCrops.posterRegion }}
            <br>Member Since {{ saleCrops.posterJoinDate.toDate() | date: 'yyyy' }}
          </div>
          <div class="divider"></div>
          <div class="example-long-small-box">
            <div class="description-box"><strong style="font-size: medium">Description</strong> 
              <br><p>
                {{ saleCrops.itemDescription }}
              </p>
            </div>
            <div class="desc-space-box"></div>
          </div>
          <div class="example-very-small-box">
            <strong style="font-size: medium">Current Bid</strong>
            <br><p>Bid Amount : 
            <br>Bidding Price :</p>
            
          </div>
        </div>
        <div class="flex-md-row">
          <button style="width: 120px;" class="btn btn-primary">Contact Seller</button>
          <div class="divider"></div>
          <button style="width: 120px;" class="btn btn-outline-primary" (click)="openDialog()">Place Bid</button>
          <div class="divider"></div>
          <button style="width: 120px;" class="btn btn-danger">Report Seller</button>
        </div>
        <div class="bid-box" *ngIf="show">
          <form (ngSubmit)="addBid(bidObj.value)">
            <input type="text" #bidObj name="bidObjID" [(ngModel)]="saleCrops.doc.id" class="form-control" value="saleCrops.doc.id"  disabled>
            <h6>Bidding Price (in Rupees per kg)</h6>
            <input type="number" name="bidPrice" [(ngModel)]="bidPrice" class="form-control" style="width: 200px">
            <h6>Bidding Amount (in kg)</h6>
            <input type="number" name="bidAmount" [(ngModel)]="bidAmount" class="form-control" style="width: 200px">
            <button class="submit" style="width: 120px;" class="btn btn-primary">Add Bid</button>
          </form>
        </div>
      </mat-expansion-panel>
    </mat-accordion>
</mat-card>
<p *ngIf="page1.done | async">I ran out of stuff to show!</p>
<app-loading-spinner *ngIf="page1.loading"></app-loading-spinner>

【问题讨论】:

    标签: angular typescript firebase google-cloud-firestore


    【解决方案1】:

    为什么你得到SellinglistComponent.html:53 ERROR Error: Function DocumentReference.set() called with invalid data. Unsupported field value: undefined (found in field ownerID) 的原因是你调用的函数是异步的。

    当您致电this.db.collection("bids").add({}) 时,this.db.collection('saleCrops').doc(this.bidObjectId).ref.get() 仍然没有回复。这就是为什么您第二次调用它时设置了this.ownerId

    您可以在 this.db.collection("bids").add({}) 之前调用 console.log(this.ownerId) 进行测试

    要提供解决方案,您必须使函数异步。

    async addBid(bidObj)

    然后你可以用 await 调用下面的代码。

    await this.db.collection('saleCrops').doc(this.bidObjectId).ref.get()

    由于这两个代码块看起来相互依赖。您可以执行以下操作。

    而不是设置this.ownerID = doc.data().posterID;

    你可以像这样返回那个值。

        await this.db.collection('saleCrops').doc(this.bidObjectId).ref.get()
            .then((doc) => {
                if (doc.exists) {
                    return doc.data().posterID;
                }
            }).then(id => {
                this.db.collection("bids").add({})
            }).catch(error => console.error(error));
    

    【讨论】: