错误 NullInjectorError:R3InjectorError(独立 [ReservarPage])[ReservasService -> ReservasService -> Firestore -> Firestore]: NullInjectorError:没有 Firestore 提供程序!
我不知道如何解决这个问题,我一直在尝试很多方法来解决这个问题,但我不能,这是我的代码
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormControl, FormGroup, FormsModule, Validators, ReactiveFormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { RouterLink } from '@angular/router';
import { MenuController } from '@ionic/angular';
import { ReservasService } from '../reservas.service';
@Component({
selector: 'app-reservar',
templateUrl: './reservar.page.html',
styleUrls: ['./reservar.page.scss'],
standalone: true,
imports: [CommonModule, FormsModule, RouterLink, IonicModule, ReactiveFormsModule ]
})
export class ReservarPage {
reservaForm = new FormGroup({
fechaInicio: new FormControl("", [Validators.required]),
lugares: new FormControl("", [Validators.required]),
puertoSalida: new FormControl("", [Validators.required]),
noches: new FormControl("", Validators.required),
huespedes: new FormControl("", Validators.required),
nombreCamarote: new FormControl("", Validators.required),
numeroCamarotes: new FormControl("", Validators.required),
nombreCrucero: new FormControl("", Validators.required)
})
async onSubmit(){
const datos = this.reservaForm.value
await this.reservasService.guardarReserva(
this.reservaForm.value.fechaInicio,
this.reservaForm.value.lugares,
this.reservaForm.value.puertoSalida,
this.reservaForm.value.noches,
this.reservaForm.value.huespedes,
this.reservaForm.value.nombreCamarote,
this.reservaForm.value.numeroCamarotes,
this.reservaForm.value.nombreCrucero)
}
constructor(public menu: MenuController, public reservasService: ReservasService) {
this.menuActive();
}
menuActive(){
this.menu.enable(true, 'menu');
}
}
```
resrvas.service.ts:
```
import { inject, Injectable } from "@angular/core";
import { addDoc, collection, Firestore } from "@angular/fire/firestore";
@Injectable({
providedIn: 'root',
})
export class ReservasService {
private firestore = inject(Firestore);
constructor( ) { }
async guardarReserva(fechaInicio: any, lugares: any, puertoSalida: any, noches: any,
huespedes: any, nombreCamarote: any, numeroCamarotes: any,
nombreCrucero: any) {
const obj ={
"fechaInicio" : fechaInicio,
"lugares" : lugares,
"puertoSalida" : puertoSalida,
"noches" : noches,
"huespedes" : huespedes,
"nombreCamarote" : nombreCamarote,
"numeroCamarotes" : numeroCamarotes,
"nombreCrucero" : nombreCrucero
};
const Ref = collection(this.firestore, 'Reservas');
await addDoc(Ref, obj);
}
}
```
authentication.service.ts:
```
import { inject, Injectable } from '@angular/core';
import { Auth } from '@angular/fire/auth';
import { createUserWithEmailAndPassword, sendPasswordResetEmail, signInWithEmailAndPassword, signOut }
from 'firebase/auth';
import { User } from 'firebase/auth';
@Injectable({
providedIn: 'root',
})
export class AuthenticationService {
private auth = inject(Auth);
constructor(
) { }
async registerUser(email: string, password:string){
return await createUserWithEmailAndPassword(this.auth, email, password)
}
async loginUser(email: string, password: string){
return await signInWithEmailAndPassword(this.auth, email,password)
}
async resetPassword(email: string){
return await sendPasswordResetEmail(this.auth, email)
}
async signOut(){
return await signOut(this.auth)
}
async getProfile():Promise <User | null> {
return new Promise<User | null>((resolve, reject) => {
this.auth.onAuthStateChanged(user => {
if (user) {
resolve(user as User);
} else {
resolve(null);
}
}, reject);
})
}
}
```
app.module.ts:
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { IonicModule } from '@ionic/angular';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app.routing.module';
import { OasisOfTheSeasPage } from './oasis-of-the-seas/oasis-of-the-seas.page';
import { environment } from 'src/environments/environment';
import { Capacitor } from '@capacitor/core';
import { getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app';
import { getAuth, indexedDBLocalPersistence, initializeAuth, provideAuth } from '@angular/fire/auth';
import { provideFirestore, getFirestore } from '@angular/fire/firestore';
import { provideStorage, getStorage } from '@angular/fire/storage';
import { provideHttpClient } from '@angular/common/http';
@NgModule({
imports: [BrowserModule, FormsModule, AppRoutingModule, IonicModule.forRoot({}),
],
providers: [
provideHttpClient(),
provideFirebaseApp(() => initializeApp(environment.firebaseConfig)),
provideAuth(() => {
if (Capacitor.isNativePlatform()) {
return initializeAuth(getApp(), {
persistence: indexedDBLocalPersistence
});
} else {
return getAuth();
}
}),
//getAuth()),
provideFirestore(() => getFirestore()),
provideStorage(() => getStorage()),
],
declarations: [AppComponent, OasisOfTheSeasPage],
bootstrap: [AppComponent],
})
export class AppModule {}
reservar.page.html:
<ion-header>
<ion-toolbar color="primary">
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title>Reservar</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<form [formGroup]="reservaForm" (ngSubmit)="onSubmit()">
<ion-item class="titulo" color="primary">
<ion-title>Fecha de Inicio del Crucero</ion-title>
</ion-item>
<ion-datetime-button class="fecha" datetime="datetime" name="fechaInicio" formName="fechaInicio"> </ion-datetime-button>
<ion-modal [keepContentsMounted]="true">
<ng-template>
<ion-datetime id="datetime"></ion-datetime>
</ng-template>
</ion-modal>
<ion-item class="titulo" color="primary">
<ion-title>Lugares para visitar</ion-title>
</ion-item>
<ion-item>
<ion-select label="Lugares para visitar:" placeholder="Que lugares quieres visitar" name="lugares" formControlName="lugares">
<ion-select-option value="alaska">Alaska</ion-select-option>
<ion-select-option value="asia">Asia</ion-select-option>
<ion-select-option value="australia&nuevazelanda">Australia y Nueva Zelanda</ion-select-option>
<ion-select-option value="canada&nuevainglaterra">Canada y Nueva Inglaterra</ion-select-option>
<ion-select-option value="canaldepanama">Canal de Panamá</ion-select-option>
<ion-select-option value="caribe">El Caribe</ion-select-option>
<ion-select-option value="europa">Europa</ion-select-option>
<ion-select-option value="hawai">Hawái</ion-select-option>
<ion-select-option value="bahamas">Las Bahamas</ion-select-option>
<ion-select-option value="mexico">México</ion-select-option>
<ion-select-option value="pacificonoroeste">Pacífico Noroeste</ion-select-option>
<ion-select-option value="pacificosur">Pacífico Sur</ion-select-option>
<ion-select-option value="transatlantico">Transatlántico</ion-select-option>
<ion-select-option value="transpacifico">Transpacífico</ion-select-option>
</ion-select>
</ion-item>
<ion-item class="titulo" color="primary">
<ion-title>Escoge el puerto de salida</ion-title>
</ion-item>
<ion-item>
<ion-select label="Puerto de Salida:" placeholder="Escoge el puerto de salida" name="puertoSalida" formControlName="puertoSalida">
<ion-select-option value="barcelona">Barcelona, España</ion-select-option>
<ion-select-option value="roma">Roma (Civitavecchia), Italia</ion-select-option>
<ion-select-option value="ravena">Rávena (Venecia), Italia</ion-select-option>
<ion-select-option value="southampton">Southampton, Inglaterra</ion-select-option>
<ion-select-option value="baltimore">Baltimore, Maryland</ion-select-option>
<ion-select-option value="boston">Boston, Massachusetts</ion-select-option>
<ion-select-option value="capeLiberty">Cape Liberty (Nueva York), Nueva Jersey</ion-select-option>
<ion-select-option value="fortLauderdale">Fort Lauderdale, Florida</ion-select-option>
<ion-select-option value="galveston">Galveston, Texas</ion-select-option>
<ion-select-option value="losAngeles">Los Ángeles, California</ion-select-option>
<ion-select-option value="miami">Miami, Florida</ion-select-option>
<ion-select-option value="nuevaOrleans">Nueva Orleans, Luisiana</ion-select-option>
<ion-select-option value="oahu">Oahu (Honolulú), Hawái</ion-select-option>
<ion-select-option value="orlando">Orlando (Puerto Cañaveral), Florida</ion-select-option>
<ion-select-option value="vancouver">Puerto de cruceros de Vancouver, (Columbia Británica)</ion-select-option>
<ion-select-option value="sanDiego">San Diego, California</ion-select-option>
<ion-select-option value="seattle">Seattle, Washington</ion-select-option>
<ion-select-option value="seward">Seward, Alaska</ion-select-option>
<ion-select-option value="tampa">Tampa, Florida</ion-select-option>
<ion-select-option value="cartagena">Cartagena, Colombia</ion-select-option>
<ion-select-option value="colon">Colón, Panamá</ion-select-option>
<ion-select-option value="sanJuan">San Juan, Puerto Rico</ion-select-option>
<ion-select-option value="brisbane">Brisbane, Australia</ion-select-option>
<ion-select-option value="sidney">Sídney, Australia</ion-select-option>
</ion-select>
</ion-item>
<ion-item class="titulo" color="primary">
<ion-title>Cantidad de noches</ion-title>
</ion-item>
<ion-item>
<ion-input label="Número de huéspedes:" placeholder="Escoge el número de huéspedes" name="huespedes" formName="huespedes"></ion-input>
</ion-item>
<div style="text-align: center">Cada 4 huéspedes puedes pedir otro camarote</div>
<ion-item class="titulo" color="primary">
<ion-title>Camarotes</ion-title>
</ion-item>
<ion-item>
<ion-select label="Camarote:" placeholder="Escoge un camarote" name="nombreCamarote" formName="nombreCamarote">
<ion-select-option value="camarotesInteriores">Camarotes Interiores</ion-select-option>
<ion-select-option value="vistaOceano">Vista al Océano</ion-select-option>
<ion-select-option value="camaroteBalcon">Camarotes con Balcón</ion-select-option>
<ion-select-option value="sunsetCornerSuite">Sunser Corner Suite</ion-select-option>
<ion-select-option value="panoramicSuite">Panoramic Suite</ion-select-option>
<ion-select-option value="infinityBalconies">Infinity Balconies</ion-select-option>
</ion-select>
</ion-item>
<ion-item class="titulo" color="primary">
<ion-title>Número de Camarotes</ion-title>
</ion-item>
<ion-item>
<ion-input label="Número de camarotes:" placeholder="Escoge el número de camarotes" name="numeroCamarotes" formName="numeroCamarotes"></ion-input>
</ion-item>
<ion-item class="titulo" color="primary">
<ion-title>Nuestra Flota</ion-title>
</ion-item>
<ion-item>
<ion-select label="Crucero:" placeholder="Escoge un crucero" name="nombreCrucero" formName="nombreCrucero">
<ion-select-option value="adventure-of-the-seas">Adventure of the Seas</ion-select-option>
<ion-select-option value="allure-of-the-seas">Allure of the Seas</ion-select-option>
<ion-select-option value="anthem-of-the-seas">Anthem of the Seas</ion-select-option>
<ion-select-option value="brilliance-of-the-seas">Brilliance of the Seas</ion-select-option>
<ion-select-option value="enchantment-of-the-seas">Enchantment of the Seas</ion-select-option>
<ion-select-option value="explorer-of-the-seas">Explorer of the Seas</ion-select-option>
<ion-select-option value="freedom-of-the-seas">Freedom of the Seas</ion-select-option>
<ion-select-option value="grandeur-of-the-seas">Grandeur of the Seas</ion-select-option>
<ion-select-option value="harmony-of-the-seas">Harmony of the Seas</ion-select-option>
<ion-select-option value="icon-of-the-seas">Icon of the Seas</ion-select-option>
<ion-select-option value="independence-of-the-seas">Independence of the Seas</ion-select-option>
<ion-select-option value="jewel-of-the-seas">Jewel of the Seas</ion-select-option>
<ion-select-option value="liberty-of-the-seas">Liberty of the Seas</ion-select-option>
<ion-select-option value="mariner-of-the-seas">Mariner of the Seas</ion-select-option>
<ion-select-option value="navigator-of-the-seas">Navigator of the Seas</ion-select-option>
<ion-select-option value="oasis-of-the-seas">Oasis of the Seas</ion-select-option>
<ion-select-option value="odyssey-of-the-seas">Odyssey of the Seas</ion-select-option>
<ion-select-option value="ovation-of-the-seas">Ovation of the Seas</ion-select-option>
<ion-select-option value="quantum-of-the-seas">Quantum of the Seas</ion-select-option>
<ion-select-option value="radiance-of-the-seas">Radiance of the Seas</ion-select-option>
<ion-select-option value="rhapsody-of-the-seas">Rhapsody of the Seas</ion-select-option>
<ion-select-option value="serenade-of-the-seas">Serenade of the Seas</ion-select-option>
<ion-select-option value="spectrum-of-the-seas">Spectrum of the Seas</ion-select-option>
<ion-select-option value="star-of-the-seas">Star of the Seas</ion-select-option>
<ion-select-option value="symphony-of-the-seas">Symphony of the Seas</ion-select-option>
<ion-select-option value="utopia-of-the-seas">Utopia of the Seas</ion-select-option>
<ion-select-option value="vision-of-the-seas">Vision of the Seas</ion-select-option>
<ion-select-option value="voyager-of-the-seas">Voyager of the Seas</ion-select-option>
<ion-select-option value="wonder-of-the-seas">Wonder of the Seas</ion-select-option>
</ion-select>
</ion-item>
<div class="boton">
<ion-button type="submit">Reservar</ion-button>
</div>
</form>
</ion-content>
I expect that when i press reservar button it saves all the data in firebase
确保您没有将
ReservasService
添加到任何延迟加载模块的提供程序数组或应用程序中的任何位置,这可能是问题所在。
ReservasService
应在 root
中提供,并且不应有任何其他实例,这些实例将无法访问 Firestore
提供程序。