如何使用 AngularFire 创建(设置)数据到 Firestore?

发布于 2025-01-09 19:14:22 字数 3259 浏览 5 评论 0 原文

我正在关注 AngularFire 快速入门教程 。我让 Read 开始工作,它在 Angular 视图中显示我的 Firestore 数据库中的数据。我很困惑如何让 Create (set) 工作。

我的 app.component.html 显示一个带有 Submit 按钮的小文本表单字段,并显示 Firestore 数据库中的值:

<form (ngSubmit)="onSubmit()">
  <input type="text" [(ngModel)]="name" name="name">
  <button type="submit" value="Submit" >Submit</button>
</form>

<ul>
  <li class="text" *ngFor="let item of items | async">
    {{item.name}}
  </li>
</ul>

我的 app.component.ts 文件有一个函数 onSubmit(),当用户单击 Submit 按钮时执行。它记录用户在文本表单字段中输入的名称。下一行抛出此错误:

TS2339: Property 'firestore' does not exist on type 'AppComponent'.

23     this.firestore.collection('items').doc('item').set({name: this.name}); // error is here

这是我的 app.component.ts

import { Component } from '@angular/core';
import { AngularFirestore } from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs';

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

export class AppComponent {

  items: Observable<any[]>;
  constructor(firestore: AngularFirestore) {
    this.items = firestore.collection('items').valueChanges();
  }

  name: string | null = null;

  onSubmit() {
    console.log(this.name);
    this.firestore.collection('items').doc('item').set({name: this.name}); // error is here
    return // return what?
  }
}

这与 英雄之旅教程:

export class HeroService {

  constructor(private logger: Logger) {  }

  getHeroes() {
    this.logger.log('Getting heroes ...');
    return HEROES;
  }
}

我的app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';

// Firebase
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFirestoreModule } from '@angular/fire/compat/firestore';
import { environment } from '../environments/environment';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFirestoreModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

视图:

在此处输入图像描述

以及我的 Firestore 数据库:

在此处输入图像描述

I'm following the AngularFire Quickstart tutorial. I got Read working, which displays the data from my Firestore database in the Angular view. I'm stumped how to get Create (set) working.

My app.component.html displays a little text form field with a Submit button, and the displays the values in the Firestore database:

<form (ngSubmit)="onSubmit()">
  <input type="text" [(ngModel)]="name" name="name">
  <button type="submit" value="Submit" >Submit</button>
</form>

<ul>
  <li class="text" *ngFor="let item of items | async">
    {{item.name}}
  </li>
</ul>

My app.component.ts file has a function onSubmit() that executes when the user clicks the Submit button. It logs the name that the user entered in the text form field. The next line throws this error:

TS2339: Property 'firestore' does not exist on type 'AppComponent'.

23     this.firestore.collection('items').doc('item').set({name: this.name}); // error is here

Here's my app.component.ts:

import { Component } from '@angular/core';
import { AngularFirestore } from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs';

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

export class AppComponent {

  items: Observable<any[]>;
  constructor(firestore: AngularFirestore) {
    this.items = firestore.collection('items').valueChanges();
  }

  name: string | null = null;

  onSubmit() {
    console.log(this.name);
    this.firestore.collection('items').doc('item').set({name: this.name}); // error is here
    return // return what?
  }
}

This is the same pattern as the Tour of Heroes tutorial:

export class HeroService {

  constructor(private logger: Logger) {  }

  getHeroes() {
    this.logger.log('Getting heroes ...');
    return HEROES;
  }
}

My app.module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';

// Firebase
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFirestoreModule } from '@angular/fire/compat/firestore';
import { environment } from '../environments/environment';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFirestoreModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

The view:

enter image description here

And my Firestore database:

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

屌丝范 2025-01-16 19:14:22

我认为这里的问题与 TypeScript 有关。我相信在这种情况下,最佳实践是在将其注入到组件的构造函数中时,在 firestore: Firestore 前面使用 private 访问修饰符,或者您正在使用它的服务,在您的情况下是app.component.ts

private 访问修饰符做了几件事:

  1. 它使属性成为类的成员(类似于您在类 firestore: any; 中声明了该属性
  2. )使属性“私有”仅在类中可用,但在模板中不可用(在开发期间 - 在生产中不强制执行)。
constructor(private firestore: AngularFirestore) {
  this.items = firestore.collection('items').valueChanges();
}

I think the issue here is related to TypeScript. I believe best-practice, in this case, would be for you to use the private access modifier in front of firestore: Firestore while injecting it into the constructor of the component or service where you are using it, in your case app.component.ts.

The private access modifier does a couple things:

  1. It makes the property a member of the class (similar to if you had declared the property in you class firestore: any;)
  2. It makes the property 'private', only available in the class but not available in the template (during development - not enforced in production).

constructor(private firestore: AngularFirestore) {
  this.items = firestore.collection('items').valueChanges();
}

聊慰 2025-01-16 19:14:22

史蒂夫的答案有效,但我不明白为什么它有效。玩弄一下,这三个都有效:

constructor(private firestore: AngularFirestore) {
constructor(protected firestore: AngularFirestore) {
constructor(public firestore: AngularFirestore) {

这不起作用:

constructor(firestore: AngularFirestore) {

根据 TypeScript 手册

Because public is already the default visibility modifier, you don’t ever need to write it on a class member, but might choose to do so for style/readability reasons.

这显然是错误的。 Read 函数无需指定 publicprivateprotected 即可工作,但 Update > 函数仅在指定 publicprivateprotected 时才起作用。

我将尝试使用 CreateDelete。然后我将发布有关此 TypeScript 行为的另一个问题。

Steve's answer works but I don't understand why it works. Playing around, all three of these work:

constructor(private firestore: AngularFirestore) {
constructor(protected firestore: AngularFirestore) {
constructor(public firestore: AngularFirestore) {

This doesn't work:

constructor(firestore: AngularFirestore) {

According to the TypeScript handbook,

Because public is already the default visibility modifier, you don’t ever need to write it on a class member, but might choose to do so for style/readability reasons.

That's clearly wrong. The Read function works without specifying public, private, or protected, but the Update function only works when public, private, or protected is specified.

I'll play around with Create and Delete. Then I'll post another question about this TypeScript behavior.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文