Angular 8 中的异常:无法解析所有参数 Angular 8
EXCEPTION in Angular 8: Can't resolve all parameters Angular 8
我在 Angular 8 中构建了一个应用程序,但我遇到了一个奇怪的问题,我无法将服务注入我的组件之一。基本上我想在一页下显示我所有的 login/register 手段,而无需仅通过管理字段进行路由。但是这个错误一次又一次地出现。
未捕获错误:无法解析 AuthTestComponent 的所有参数:([object Object], [object Object], ?).
我的auth.service.ts文件:-
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';
import { Router } from '@angular/router'
@Injectable({
providedIn: 'root'
})
export class AuthService {
authUrl = "API"
constructor(private http: HttpClient, private router: Router) { }
registerUser(email: string, password: string) {
return this.http.post<any>(this.authUrl + "user-register", {
email: email,
password: password,
// c_password: password,
token: true
}).pipe(catchError(this.handleError))
}
LoginUser(email: string, password: string) {
return this.http.post<any>(this.authUrl + "user-login", {
email: email,
password: password,
access_token: true
}).pipe(catchError(this.handleError))
}
loggedIn() {
return !!localStorage.getItem('access_token')
}
getToken() {
return localStorage.getItem('access_token')
}
logoutUser() {
localStorage.removeItem('access_token');
this.router.navigate(['login'])
}
private handleError(errorRes: HttpErrorResponse) {
let errorMessage = "An Unkown error occured!";
if (!errorRes.error.error.errors || !errorRes.error.error.email[0]) {
return throwError(errorMessage)
}
switch (errorRes.error.error.email[0]) {
case 'The email has already been taken.':
errorMessage = 'The email already exists!'
break;
}
// switch (errorRes.error.error[0]) {
// case 'Password or Email not matched':
// errorMessage = 'Please Sign Up to continue!'
// case 'INVALID_PASSWORD':
// errorMessage = 'This password is not correct.'
// }
return throwError(errorMessage);
}
sendPasswordResetLink(email: string) {
return this.http.post<any>(this.authUrl + "updatepassword", {
email: email
}).pipe(catchError(this.handleError))
}
}
我的组件文件:-
import { Component, Inject } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
// import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { $animations } from './login-animations';
import { $providers } from './login-providers';
import { $pages } from './login-pages';
import { from } from 'rxjs';
import { AuthService } from '../services/auth/auth.service';
import { Router } from '@angular/router';
export type loginAction = 'register' | 'signIn' | 'forgotPassword' | 'signOut';
@Component({
selector: 'app-auth-test',
templateUrl: './auth-test.component.html',
styleUrls: ['./auth-test.component.css'],
animations: $animations
})
export class AuthTestComponent {
readonly providers = $providers;
private pages = $pages;
private page: loginAction;
// private code: string;
readonly form: FormGroup;
// private password2: FormControl;
private email: FormControl;
private password: FormControl;
public error = null;
// private newPassword: FormControl;
isLoading = false;
public progress = false;
constructor(private auth: AuthService, private router: Router, private action: loginAction) {
// Form controls
// this.password2 = new FormControl(null, Validators.required);
this.email = new FormControl(null, [Validators.required, Validators.email]);
this.password = new FormControl(null, Validators.required);
// this.newPassword = new FormControl(null, Validators.required);
// Empty form group
this.form = new FormGroup({});
// Populates the form according to the page
this.switchPage(this.page = action);
}
get currentPage() { return this.pages[this.page || 'signIn']; }
private switchPage(page: loginAction) {
// Removes all the controls from the form group
Object.keys(this.form.controls).forEach(control => {
this.form.removeControl(control);
});
// Add the relevant controls to the form according to selected page
switch (this.page = page) {
case 'register':
this.form.addControl('email', this.email);
this.form.addControl('password', this.password);
// this.form.addControl('password2', this.password2);
break;
default:
// case 'signIn':
// this.form.addControl('email', this.email);
// this.form.addControl('password', this.password);
// break;
// case 'forgotPassword':
// this.form.addControl('email', this.email);
// break;
/*
case 'resetPassword':
this.form.addControl('newPassword', this.newPassword);
break;
*/
}
}
// private showError(error: string) {
// this.error = error;
// this.progress = false;
// setTimeout(() => this.error = null, 5000);
// }
public activate(action: loginAction) {
this.progress = true;
switch (action) {
default:
// case 'signIn':
// this.signIn(this.email.value, this.password.value);
// break;
case 'register':
this.registerNew(this.email.value, this.password.value);
break;
// case 'forgotPassword':
// this.forgotPassword(this.email.value);
// break;
/*
case 'resetPassword':
this.resetPassword( this.code, this.newPassword.value );
break;
*/
}
}
private registerNew(email: string, password: string) {
// Registering a new user with a email/password
this.auth.registerUser(email, password).subscribe(
res => {
console.log(res);
localStorage.setItem('token', res.token)
this.isLoading = false;
this.router.navigate(['login']);
},
errorMessage => {
console.log(errorMessage);
this.error = errorMessage;
this.isLoading = false;
}
);
}
}
HTML表格文件-:
<div [@vanish]="page">
<h1 class="mat-title">{{ currentPage.title }}</h1>
<p class="mat-small">{{ currentPage.message }}</p>
</div>
<form [formGroup]="form" fxLayout="column" fxLayoutAlign="space-around stretch" fxLayoutGap="10px"
(ngSubmit)="activate(page)" *ngIf="page !== 'promptEmail' && page !== 'verifyEmail' && page !== 'recoverEmail'">
<!-- ERROR MESSAGE -->
<mat-error *ngIf="error" @inflate>{{ error }}</mat-error>
<!-- NAME
<mat-form-field appearance="legacy" *ngIf="form.contains('confirm')" @inflate>
<mat-label>Full name</mat-label>
<input matInput formControlName="confirm">
<mat-error *ngIf="form.controls.confirm.errors?.required">
Please specify your name here
</mat-error>
</mat-form-field> -->
<!-- EMAIL -->
<mat-form-field appearance="legacy" *ngIf="form.contains('email')" @inflate>
<mat-label>Email</mat-label>
<input matInput formControlName="email">
<mat-error *ngIf="form.controls.email.errors?.required">
Please specify an email address
</mat-error>
<mat-error *ngIf="form.controls.email.errors?.email">
Ooops! it looks like this is not a valid email
</mat-error>
</mat-form-field>
<!-- PASSWORD -->
<mat-form-field appearance="legacy" *ngIf="form.contains('password')" @inflate>
<mat-label>Password</mat-label>
<input matInput [type]="hidePassword ? 'password' : 'text'" formControlName="password">
<mat-icon matSuffix (click)="hidePassword = !hidePassword">
{{ hidePassword ? 'visibility_off' : 'visibility'}}
</mat-icon>
<mat-error *ngIf="form.controls.password.errors?.required">
A password is required
</mat-error>
</mat-form-field>
<!-- confirm PASSWORD -->
<mat-form-field appearance="legacy" *ngIf="form.contains('password')" @inflate>
<mat-label>Password</mat-label>
<input matInput [type]="hidePassword ? 'password' : 'text'" formControlName="password2">
<mat-icon matSuffix (click)="hidePassword = !hidePassword">
{{ hidePassword ? 'visibility_off' : 'visibility'}}
</mat-icon>
<mat-error *ngIf="form.controls.password2.errors?.required">
A password is required
</mat-error>
<mat-hint class="mat-link" align="end" (click)="switchPage('forgotPassword')" *ngIf="page == 'signIn'"
@inflate>Forgot password?</mat-hint>
</mat-form-field>
<!-- NEW EMAIL -->
<!-- <mat-form-field appearance="legacy" *ngIf="form.contains('newEmail')" @inflate>
<mat-label>New email</mat-label>
<input matInput formControlName="newEmail">
<mat-error *ngIf="form.controls.newEmail.errors?.required">
A new email is required
</mat-error>
<mat-error *ngIf="form.controls.newEmail.errors?.email">
This email looks wrong
</mat-error>
</mat-form-field> -->
<!-- NEW PASSWORD -->
<!-- <mat-form-field appearance="legacy" *ngIf="form.contains('newPassword')" @inflate>
<mat-label>New password</mat-label>
<input matInput formControlName="newPassword">
<mat-error *ngIf="form.controls.newPassword.errors?.required">
A new password is required
</mat-error>
</mat-form-field> -->
<!-- ACTION BUTTON -->
<button mat-stroked-button color="primary" type="submit" [disabled]="!form.valid" class="btn">
{{ currentPage.caption }}
</button>
<mat-progress-bar *ngIf="progress" mode="indeterminate" @inflate></mat-progress-bar>
</form>
<p class="mat-small" *ngIf="page == 'signIn'">
Are you a new user? <span class="mat-link" (click)="switchPage('register')">Register</span>
</p>
<p class="mat-small" *ngIf="page === 'register' || page === 'forgotPassword'">
Already have login and password? <span class="mat-link" (click)="switchPage('signIn')">Sign-in</span>
</p>
<!-- SIGN-IN PROVIDERS -->
<div fxLayout="column" fxLayoutAlign="center center" *ngIf="page == 'signIn'" @inflate>
<p class="mat-small">or sign-in with:</p>
<div fxLayout="row wrap" fxLayoutAlign="center center" fxLayoutGap="10px">
<button mat-icon-button *ngFor="let p of providers" (click)="signInWith(p.name)">
<mat-icon class="providers" [fontSet]="p.icon.split(':')[0]" [fontIcon]="p.icon.split(':')[1]"
[ngStyle]="{ color: p.color }">
</mat-icon>
</button>
</div>
</div>
看来问题出在这里:
private action: loginAction
loginAction
是类型,不能注入
例如,您可以使用 InjectionToken
const LOGIN_ACTION = new InjectionToken<loginAction>('Login action token');
...
@Inject(LOGIN_ACTION) private action: loginAction
错误跟踪提供了有关正在发生的事情的线索:([object Object], [object Object], ?)
。在 Angular 中,它一直是对象(即使是模块也只是对象周围的一些语法糖)。
由于错误消息中的第一项是对象,我们可以假设构造函数中引用的前两个服务的依赖注入是成功的。错误消息中的 ?
(第三个位置)表示注入最终依赖项可能存在问题,即 private action: loginAction
.
Angular guide on dependency injection (DI) 通过调出 "dependencies are services or objects" 为其运作方式提供了一些背景信息。您看到的错误可能是由于尝试注入不可注入的实体(即字符串)引起的。
查看组件在代码中的实现方式可能会有所帮助,例如,相应的 HTML。除了其他响应之一中提供的 InjectionToken
示例外,您还可以调查 Input
属性(请参阅组件上的 Angular Input 是否允许您传递必要的页面动作)。
我在 Angular 8 中构建了一个应用程序,但我遇到了一个奇怪的问题,我无法将服务注入我的组件之一。基本上我想在一页下显示我所有的 login/register 手段,而无需仅通过管理字段进行路由。但是这个错误一次又一次地出现。
未捕获错误:无法解析 AuthTestComponent 的所有参数:([object Object], [object Object], ?).
我的auth.service.ts文件:-
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';
import { Router } from '@angular/router'
@Injectable({
providedIn: 'root'
})
export class AuthService {
authUrl = "API"
constructor(private http: HttpClient, private router: Router) { }
registerUser(email: string, password: string) {
return this.http.post<any>(this.authUrl + "user-register", {
email: email,
password: password,
// c_password: password,
token: true
}).pipe(catchError(this.handleError))
}
LoginUser(email: string, password: string) {
return this.http.post<any>(this.authUrl + "user-login", {
email: email,
password: password,
access_token: true
}).pipe(catchError(this.handleError))
}
loggedIn() {
return !!localStorage.getItem('access_token')
}
getToken() {
return localStorage.getItem('access_token')
}
logoutUser() {
localStorage.removeItem('access_token');
this.router.navigate(['login'])
}
private handleError(errorRes: HttpErrorResponse) {
let errorMessage = "An Unkown error occured!";
if (!errorRes.error.error.errors || !errorRes.error.error.email[0]) {
return throwError(errorMessage)
}
switch (errorRes.error.error.email[0]) {
case 'The email has already been taken.':
errorMessage = 'The email already exists!'
break;
}
// switch (errorRes.error.error[0]) {
// case 'Password or Email not matched':
// errorMessage = 'Please Sign Up to continue!'
// case 'INVALID_PASSWORD':
// errorMessage = 'This password is not correct.'
// }
return throwError(errorMessage);
}
sendPasswordResetLink(email: string) {
return this.http.post<any>(this.authUrl + "updatepassword", {
email: email
}).pipe(catchError(this.handleError))
}
}
我的组件文件:-
import { Component, Inject } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
// import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { $animations } from './login-animations';
import { $providers } from './login-providers';
import { $pages } from './login-pages';
import { from } from 'rxjs';
import { AuthService } from '../services/auth/auth.service';
import { Router } from '@angular/router';
export type loginAction = 'register' | 'signIn' | 'forgotPassword' | 'signOut';
@Component({
selector: 'app-auth-test',
templateUrl: './auth-test.component.html',
styleUrls: ['./auth-test.component.css'],
animations: $animations
})
export class AuthTestComponent {
readonly providers = $providers;
private pages = $pages;
private page: loginAction;
// private code: string;
readonly form: FormGroup;
// private password2: FormControl;
private email: FormControl;
private password: FormControl;
public error = null;
// private newPassword: FormControl;
isLoading = false;
public progress = false;
constructor(private auth: AuthService, private router: Router, private action: loginAction) {
// Form controls
// this.password2 = new FormControl(null, Validators.required);
this.email = new FormControl(null, [Validators.required, Validators.email]);
this.password = new FormControl(null, Validators.required);
// this.newPassword = new FormControl(null, Validators.required);
// Empty form group
this.form = new FormGroup({});
// Populates the form according to the page
this.switchPage(this.page = action);
}
get currentPage() { return this.pages[this.page || 'signIn']; }
private switchPage(page: loginAction) {
// Removes all the controls from the form group
Object.keys(this.form.controls).forEach(control => {
this.form.removeControl(control);
});
// Add the relevant controls to the form according to selected page
switch (this.page = page) {
case 'register':
this.form.addControl('email', this.email);
this.form.addControl('password', this.password);
// this.form.addControl('password2', this.password2);
break;
default:
// case 'signIn':
// this.form.addControl('email', this.email);
// this.form.addControl('password', this.password);
// break;
// case 'forgotPassword':
// this.form.addControl('email', this.email);
// break;
/*
case 'resetPassword':
this.form.addControl('newPassword', this.newPassword);
break;
*/
}
}
// private showError(error: string) {
// this.error = error;
// this.progress = false;
// setTimeout(() => this.error = null, 5000);
// }
public activate(action: loginAction) {
this.progress = true;
switch (action) {
default:
// case 'signIn':
// this.signIn(this.email.value, this.password.value);
// break;
case 'register':
this.registerNew(this.email.value, this.password.value);
break;
// case 'forgotPassword':
// this.forgotPassword(this.email.value);
// break;
/*
case 'resetPassword':
this.resetPassword( this.code, this.newPassword.value );
break;
*/
}
}
private registerNew(email: string, password: string) {
// Registering a new user with a email/password
this.auth.registerUser(email, password).subscribe(
res => {
console.log(res);
localStorage.setItem('token', res.token)
this.isLoading = false;
this.router.navigate(['login']);
},
errorMessage => {
console.log(errorMessage);
this.error = errorMessage;
this.isLoading = false;
}
);
}
}
HTML表格文件-:
<div [@vanish]="page">
<h1 class="mat-title">{{ currentPage.title }}</h1>
<p class="mat-small">{{ currentPage.message }}</p>
</div>
<form [formGroup]="form" fxLayout="column" fxLayoutAlign="space-around stretch" fxLayoutGap="10px"
(ngSubmit)="activate(page)" *ngIf="page !== 'promptEmail' && page !== 'verifyEmail' && page !== 'recoverEmail'">
<!-- ERROR MESSAGE -->
<mat-error *ngIf="error" @inflate>{{ error }}</mat-error>
<!-- NAME
<mat-form-field appearance="legacy" *ngIf="form.contains('confirm')" @inflate>
<mat-label>Full name</mat-label>
<input matInput formControlName="confirm">
<mat-error *ngIf="form.controls.confirm.errors?.required">
Please specify your name here
</mat-error>
</mat-form-field> -->
<!-- EMAIL -->
<mat-form-field appearance="legacy" *ngIf="form.contains('email')" @inflate>
<mat-label>Email</mat-label>
<input matInput formControlName="email">
<mat-error *ngIf="form.controls.email.errors?.required">
Please specify an email address
</mat-error>
<mat-error *ngIf="form.controls.email.errors?.email">
Ooops! it looks like this is not a valid email
</mat-error>
</mat-form-field>
<!-- PASSWORD -->
<mat-form-field appearance="legacy" *ngIf="form.contains('password')" @inflate>
<mat-label>Password</mat-label>
<input matInput [type]="hidePassword ? 'password' : 'text'" formControlName="password">
<mat-icon matSuffix (click)="hidePassword = !hidePassword">
{{ hidePassword ? 'visibility_off' : 'visibility'}}
</mat-icon>
<mat-error *ngIf="form.controls.password.errors?.required">
A password is required
</mat-error>
</mat-form-field>
<!-- confirm PASSWORD -->
<mat-form-field appearance="legacy" *ngIf="form.contains('password')" @inflate>
<mat-label>Password</mat-label>
<input matInput [type]="hidePassword ? 'password' : 'text'" formControlName="password2">
<mat-icon matSuffix (click)="hidePassword = !hidePassword">
{{ hidePassword ? 'visibility_off' : 'visibility'}}
</mat-icon>
<mat-error *ngIf="form.controls.password2.errors?.required">
A password is required
</mat-error>
<mat-hint class="mat-link" align="end" (click)="switchPage('forgotPassword')" *ngIf="page == 'signIn'"
@inflate>Forgot password?</mat-hint>
</mat-form-field>
<!-- NEW EMAIL -->
<!-- <mat-form-field appearance="legacy" *ngIf="form.contains('newEmail')" @inflate>
<mat-label>New email</mat-label>
<input matInput formControlName="newEmail">
<mat-error *ngIf="form.controls.newEmail.errors?.required">
A new email is required
</mat-error>
<mat-error *ngIf="form.controls.newEmail.errors?.email">
This email looks wrong
</mat-error>
</mat-form-field> -->
<!-- NEW PASSWORD -->
<!-- <mat-form-field appearance="legacy" *ngIf="form.contains('newPassword')" @inflate>
<mat-label>New password</mat-label>
<input matInput formControlName="newPassword">
<mat-error *ngIf="form.controls.newPassword.errors?.required">
A new password is required
</mat-error>
</mat-form-field> -->
<!-- ACTION BUTTON -->
<button mat-stroked-button color="primary" type="submit" [disabled]="!form.valid" class="btn">
{{ currentPage.caption }}
</button>
<mat-progress-bar *ngIf="progress" mode="indeterminate" @inflate></mat-progress-bar>
</form>
<p class="mat-small" *ngIf="page == 'signIn'">
Are you a new user? <span class="mat-link" (click)="switchPage('register')">Register</span>
</p>
<p class="mat-small" *ngIf="page === 'register' || page === 'forgotPassword'">
Already have login and password? <span class="mat-link" (click)="switchPage('signIn')">Sign-in</span>
</p>
<!-- SIGN-IN PROVIDERS -->
<div fxLayout="column" fxLayoutAlign="center center" *ngIf="page == 'signIn'" @inflate>
<p class="mat-small">or sign-in with:</p>
<div fxLayout="row wrap" fxLayoutAlign="center center" fxLayoutGap="10px">
<button mat-icon-button *ngFor="let p of providers" (click)="signInWith(p.name)">
<mat-icon class="providers" [fontSet]="p.icon.split(':')[0]" [fontIcon]="p.icon.split(':')[1]"
[ngStyle]="{ color: p.color }">
</mat-icon>
</button>
</div>
</div>
看来问题出在这里:
private action: loginAction
loginAction
是类型,不能注入
例如,您可以使用 InjectionToken
const LOGIN_ACTION = new InjectionToken<loginAction>('Login action token');
...
@Inject(LOGIN_ACTION) private action: loginAction
错误跟踪提供了有关正在发生的事情的线索:([object Object], [object Object], ?)
。在 Angular 中,它一直是对象(即使是模块也只是对象周围的一些语法糖)。
由于错误消息中的第一项是对象,我们可以假设构造函数中引用的前两个服务的依赖注入是成功的。错误消息中的 ?
(第三个位置)表示注入最终依赖项可能存在问题,即 private action: loginAction
.
Angular guide on dependency injection (DI) 通过调出 "dependencies are services or objects" 为其运作方式提供了一些背景信息。您看到的错误可能是由于尝试注入不可注入的实体(即字符串)引起的。
查看组件在代码中的实现方式可能会有所帮助,例如,相应的 HTML。除了其他响应之一中提供的 InjectionToken
示例外,您还可以调查 Input
属性(请参阅组件上的 Angular Input 是否允许您传递必要的页面动作)。