Хорошо, вот и моя странная ситуация. Я создал проект Ioni c с боковой навигацией. Затем я создал простой компонент входа в систему для использования с Firebase. Форма работает как чудо, она срабатывает при изменении поля и отображает ошибки проверки. Теперь мой следующий шаг - отключить боковое меню, когда пользователь вошел в систему. По какой-то причине, когда я добрался до app.component.ts, где обрабатывается боковое меню logi c, я добавляю наблюдаемое в функцию ngOnInit , отключение меню работает, но реактивная форма перестает работать.
Вот мой компонент входа в систему:
login.module.ts:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { LoginPageRoutingModule } from './login-routing.module';
import { LoginPage } from './login.page';
import { ComponentsModule } from '../../../components/components.module'
@NgModule({
imports: [
CommonModule,
ReactiveFormsModule,
IonicModule,
LoginPageRoutingModule,
ComponentsModule
],
declarations: [LoginPage]
})
export class LoginPageModule {}
login.page. html
<form [formGroup]="loginForm" (ngSubmit)="login(loginForm.value)" novalidate>
<ion-list>
<ion-item>
<ion-label position="floating" color="primary">Email</ion-label>
<ion-input type="email" formControlName="email"></ion-input>
</ion-item>
<div class="validation-errors">
<ng-container *ngFor="let v of validation_messages.email">
<ion-text color="danger" *ngIf="email.hasError(v.type) && (email.dirty || email.touched)">
<p class="ion-padding-start">
{{ v.message }}
</p>
</ion-text>
</ng-container>
</div>
<ion-item>
<ion-label position="floating" color="primary">Password</ion-label>
<ion-input type="password" formControlName="password"></ion-input>
</ion-item>
<div class="validation-errors">
<ng-container *ngFor="let v of validation_messages.password">
<ion-text color="danger" *ngIf="password.hasError(v.type) && (password.dirty || password.touched)">
<p class="ion-padding-start">
{{ v.message }}
</p>
</ion-text>
</ng-container>
</div>
</ion-list>
<ion-button class="submit-btn" type="submit" expand="block" [disabled]="!loginForm.valid">Login</ion-button>
<ion-text color="danger">
<p class="ion-padding-start">
{{ errorMessage }}
</p>
</ion-text>
<ion-text color="success">
<p class="ion-padding-start">
{{ successMessage }}
</p>
</ion-text>
<p class="go-to-register">No account yet? <a [routerLink]="['/register']">Create an account.</a></p>
{{loginForm.value | json}}
</form>
вход. page.ts:
import { Component, OnInit, NgZone } from '@angular/core';
import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';
import { AuthService } from '../../../services/auth.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {
loginForm: FormGroup;
testForm: FormGroup;
errorMessage: string = "";
successMessage: string = "";
errorMessageFB: string = "";
validation_messages = {
'email': [
{ type: 'required', message: 'Email is required.' },
{ type: 'email', message: 'Enter a valid email.' }
],
'password': [
{ type: 'required', message: 'Password is required.' },
{ type: 'minlength', message: 'Password need to be at least 6 characters long.' }
]
}
constructor(
private formBuilder: FormBuilder,
private authService: AuthService,
private router: Router,
private ngZone: NgZone
) { }
ngOnInit() {
this.loginForm = this.formBuilder.group({
email: new FormControl('', Validators.compose([
Validators.required,
Validators.email
])),
password: new FormControl('', Validators.compose([
Validators.required,
Validators.minLength(6)
]))
});
}
login(value: any){
}
loginWithFB(){
}
get email() { return this.loginForm.get('email'); }
get password() { return this.loginForm.get('password'); }
}
Пока все хорошо, это работает:
Теперь у меня есть служба для входа в систему и зарегистрируйте пользователя, который работает до сих пор:
auth.service.ts
import { Injectable } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import { Facebook, FacebookLoginResponse } from '@ionic-native/facebook/ngx';
import { Platform } from '@ionic/angular';
import { auth } from 'firebase/app';
import { resolve } from 'url';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AuthService {
user$: Observable<firebase.User>;
isLoggedIn$: Observable<boolean>;
isLoggedOut$: Observable<boolean>;
constructor(
private afAuth: AngularFireAuth,
private fb: Facebook,
private platform: Platform
) { }
init(){
this.user$ = this.afAuth.user;
this.isLoggedIn$ = this.afAuth.authState.pipe(map(user => !!user));
this.isLoggedOut$ = this.isLoggedIn$.pipe(map(loggedIn => !loggedIn));
}
loginWithFB(): Promise<auth.UserCredential>{
if (this.platform.is("capacitor")) {
return this.loginNativeFB();
} else {
return this.loginBrowserFB();
}
}
loginBrowserFB(){
return new Promise<auth.UserCredential>((resolve, reject) => {
const provider = new auth.FacebookAuthProvider();
this.afAuth.signInWithPopup(provider).then((res) => {
resolve(res);
}, (err) => {
reject(err);
})
});
}
loginNativeFB(){
return new Promise<auth.UserCredential>((resolve, reject) => {
this.fb.login(['email', 'public_profile']).then((response: FacebookLoginResponse) => {
if (response.authResponse) {
const credential = auth.FacebookAuthProvider.credential(
response.authResponse.accessToken
);
this.afAuth.signInWithCredential(credential).then((res) => {
resolve(res);
}, (rej) => {
reject(rej);
})
}
}, (err) => {
console.log(err);
reject(err);
})
});
}
doRegister(value: any){
return new Promise<any>((resolve, reject) => {
this.afAuth.createUserWithEmailAndPassword(value.email, value.password).then(
res => resolve(res),
err => reject(err)
)
})
}
doLogin(value: any){
return new Promise<any>((resolve, reject) => {
this.afAuth.signInWithEmailAndPassword(value.email, value.password).then(
res => resolve(res),
err => reject(err)
)
})
}
doLogout(){
return new Promise<any>((resolve, reject) => {
this.afAuth.signOut().then(() => {
resolve();
}).catch((error) => {
console.log(error);
reject();
})
})
}
}
Теперь вот проблема: я хочу скрыть боковое меню с помощью наблюдаемого. Итак, я go отправляю: app.component.ts и делаю следующее:
import { Component, OnInit } from '@angular/core';
import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AuthService } from './services/auth.service'
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss']
})
export class AppComponent implements OnInit {
public selectedIndex = 0;
public appPages = [
{
title: 'Inbox',
url: '/folder/Inbox',
icon: 'mail'
},
{
title: 'Outbox',
url: '/folder/Outbox',
icon: 'paper-plane'
},
{
title: 'Favorites',
url: '/folder/Favorites',
icon: 'heart'
},
{
title: 'Archived',
url: '/folder/Archived',
icon: 'archive'
},
{
title: 'Trash',
url: '/folder/Trash',
icon: 'trash'
},
{
title: 'Spam',
url: '/folder/Spam',
icon: 'warning'
}
];
public labels = ['Family', 'Friends', 'Notes', 'Work', 'Travel', 'Reminders'];
disableMenu: boolean;
user: firebase.User;
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar,
private authService: AuthService
) {
this.initializeApp();
}
initializeApp() {
this.authService.init();
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
ngOnInit() {
!!!!!!!!!! HERE I ADD THIS SUBSBRIBE AND THIs BREAK THE FORM !!!!!!!!!!
this.authService.isLoggedOut$.subscribe((loggedOut) => {
this.disableMenu = loggedOut;
});
this.authService.user$.subscribe((user) => {
this.user = user;
});
!!!!!!!!!! IF I REMOVE THIS IT START WORKING AGAIN !!!!!!!!!!!!!!!!!!!!
const path = window.location.pathname.split('folder/')[1];
if (path !== undefined) {
this.selectedIndex = this.appPages.findIndex(page => page.title.toLowerCase() === path.toLowerCase());
}
}
}
Добавляя эти наблюдаемые в код в ngOnInit, моя форма перестает работать. В консоли не отображаются ошибки.
Я что-то упустил? Спасибо
Мне удалось это исправить, добавив ngIf в форму, например:
<form *ngIf="loginForm" [formGroup]="loginForm" (ngSubmit)="login(loginForm.value)" novalidate>
Но я хотел бы еще и объяснение, почему это происходит.
Модуль приложения:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { AngularFireModule } from '@angular/fire';
import { AngularFireAuthModule } from '@angular/fire/auth';
import { AngularFirestoreModule } from '@angular/fire/firestore';
import { AngularFireAuthGuard } from '@angular/fire/auth-guard';
import { environment } from '../environments/environment';
import { Facebook } from "@ionic-native/facebook/ngx";
import { Geolocation } from '@ionic-native/geolocation/ngx';
import { GoogleMaps } from '@ionic-native/google-maps/ngx'
@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
BrowserModule,
IonicModule.forRoot(),
AppRoutingModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule,
AngularFirestoreModule
],
providers: [
StatusBar,
SplashScreen,
Facebook,
Geolocation,
GoogleMaps,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
AngularFireAuthGuard
],
bootstrap: [AppComponent]
})
export class AppModule {}