NullInjectorError: No provider for MatDialogRef
NullInjectorError: No provider for MatDialogRef
我无法按照文档中的描述注入 MatDialogRef:https://material.angular.io/components/dialog/overview
当我尝试这样做时出现错误:
错误错误:StaticInjectorError[MatDialogRef]:
StaticInjectorError [MatDialogRef]:
NullInjectorError:没有 MatDialogRef 的提供者!
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import {
MatInputModule,
MatDialogModule,
MatProgressSpinnerModule,
MatButtonModule,
MatDialog,
MatDialogRef
} from '@angular/material';
import { ApiModule } from '../api/api.module';
import { RoutingModule } from '../routing/routing.module';
import { RegistrationComponent } from './components/registration.component';
import { LoginComponent } from './components/login.component';
import { AccountService } from './services/account.service';
@NgModule({
imports: [
BrowserModule,
MatInputModule,
MatDialogModule,
MatProgressSpinnerModule,
MatButtonModule,
FormsModule,
RoutingModule,
ApiModule
],
declarations: [
RegistrationComponent,
LoginComponent
],
entryComponents: [
LoginComponent,
RegistrationComponent
],
providers: [
AccountService,
MatDialog,
MatDialogRef
]
})
export class AccountModule {}
home.component.ts
import { Component } from '@angular/core';
import { MatDialog } from '@angular/material';
import { RegistrationComponent } from '../account/components/registration.component';
@Component({
moduleId: module.id.replace('compiled', 'app'),
templateUrl: 'home.component.html'
})
export class HomeComponent
{
constructor(private modalService: MatDialog) {}
public openModal() : void
{
let dialog = this.modalService.open(RegistrationComponent, {});
}
}
registration.component.ts
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { MatDialogRef } from '@angular/material/dialog';
import { User } from '../../../models/domain/User';
import { ApiUserService } from '../../api/entity-services/user.service';
import { AuthService } from '../../auth/auth.service';
import { AccountService } from '../services/account.service'
@Component({
selector: 'registration-component',
templateUrl: 'app/modules/account/templates/registration.component.html'
})
export class RegistrationComponent
{
public user :User = new User();
public errorMessage :string;
public isLoading :boolean;
constructor
(
private userService :ApiUserService,
private authService :AuthService,
private accountService :AccountService,
private router :Router,
public dialogRef :MatDialogRef<RegistrationComponent>
)
{
this.isLoading = false;
}
public onSubmit(e) :void
{
e.preventDefault();
this.isLoading = true;
this.userService
.Create(this.user)
.subscribe(
user =>
{
this.user.id = user.id;
this.user.login = user.login;
this.authService
.Login(this.user)
.subscribe(
token =>
{
this.accountService.Load()
.subscribe(
account =>
{
this.user = account;
this.isLoading = false;
this.dialogRef.close();
let redirectRoute = account.activeScopeId
? `/scope/${account.activeScopeId}`
: '/scope-list/';
this.router.navigate([redirectRoute]);
},
error => this.errorMessage = <any>error
);
},
error => this.errorMessage = <any>error
);
},
error => this.errorMessage = <any>error
);
}
}
这可能是因为您没有包含 Angular 动画工作所需的 Web 动画 API polyfill,因为它依赖于 API.
这里是 caniuse 适用于本机支持它的浏览器。目前只有 Chrome、Firefox 和 Opera 支持 Web Animations API。
无论如何,您必须按照以下步骤来获得 polyfill:
在终端中,在您的控制台中输入以下内容:
npm install web-animations-js
安装完成后,取消注释 polyfills.ts
中 Angular Animations 的行(如果不存在则添加):
import 'web-animations-js'; // Uncomment this line
或者,您可以尝试从单独的端点导入模块,如下所示:
发件人:
import { MatButtonModule, MatDialogModule } from '@angular/material';
收件人:
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
感谢@Edric,我通过从 @angular/material/dialog
而不是 @angular/material
导入 MatDialogModule
、MatDialog
和 MatDialogRef
解决了这个问题
- 在您的模块中:仅从 angular/material 导入 MatDialogModule 就足够了。不需要导入和提供:MatDialogRef
- 在你的代码中 DialogComponent
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material';
- 以上是我遵循的步骤。不确定为什么需要从对话框中导入它
- 但是,能否说明一下您在 html/template 中使用的选择器?如果您在模板中使用了 "registration-component",这可能就是您会收到此错误的原因。我从 Material 指南中尝试了完全相同的示例。我不小心用了 'dialog-overview-example-dialog' 而不是 'dialog-overview-example'。 = 我遇到了和你一样的错误。
我在向要在多个组件中共享的服务添加对话框时遇到此错误。只是为了澄清,在将对话框移动到服务之前,应用程序中不存在错误。解决方案是在主模块
中包含自定义提供程序 MatDialogRef
import { DialogService } from './services/dialog.service';
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
...
imports: [
...
MatDialogModule
],
providers: [
{
provide: MatDialogRef,
useValue: {}
},
DialogService
],
...
有了这个提供者,服务作为一个单例工作,我的对话框被共享,并且提供者错误消失了。
此错误可能是由于在调用 MatDialog::open 的组件中注入 MatDialogRef
而不是在传递给 open 方法的组件中造成的。传递给 MatDialog open 方法的组件应该像 the example.
中那样在其构造函数中注入 MatDialogRef
@Component({
selector: 'dialog-overview-example-dialog',
templateUrl: 'dialog-overview-example-dialog.html',
})
export class DialogOverviewExampleDialog {
constructor(
public dialogRef: MatDialogRef<DialogOverviewExampleDialog>,
@Inject(MAT_DIALOG_DATA) public data: DialogData) {}
onNoClick(): void {
this.dialogRef.close();
}
}
对我来说,问题是我将我的对话框组件添加到其他一些 HTML 模板只是为了测试它。一旦我删除它,OP 中的错误就消失了,它就起作用了。
例如您正在使用 app-checkout
如果您在 'dialog' 和 'normal' 中使用一个组件,则可能会在正常 html 文件中添加 app-checkout
。
解决方案 1:
删除 <app-checkout> </app-checkout>
如果您不需要以正常方式将其导入 html 文件
解决方案 2 在对话框和 html 文件中使用。而不是这个:
// ... something have selector: "app-checkout",
constructor(
public dialogRef: MatDialogRef<CheckoutComponent>,
@Inject(MAT_DIALOG_DATA) public dialogData: any
) {}
你需要注入它(使其成为可选注入):
这样:
constructor(
// only need the @Optional() before the public dialogRef
@Optional() public dialogRef: MatDialogRef<CheckoutComponent>,
@Inject(MAT_DIALOG_DATA) public dialogData: any
) {
}
或者这样:
// ... the same above
private dialogRef = null;
private dialogData;
constructor(private injector: Injector) {
this.dialogRef = this.injector.get(MatDialogRef, null);
this.dialogData = this.injector.get(MAT_DIALOG_DATA, null);
}
从构造函数中删除 dialogRef:
https://stackblitz.com/edit/angular-dialog-update?file=src%2Fapp%2Fapp.component.ts
除上述所有情况外,如果您在应用的任何模板文件中引用了组件选择器,您也可能会遇到此错误。 MatDialog 组件只能由 MatDialog.dialog.open() 方法调用,而不是通过组件选择器
不幸的是,由于多种原因,可能会抛出相同的错误消息。
我遇到了这个错误并修复了它你需要做的是
检查你是否像这样在 typescript 文件中插入了 import 语句
从“@angular/material/dialog”导入 {MAT_DIALOG_DATA, MatDialogRef};
检查构造函数
constructor(@Optional() public dialogRef: MatDialogRef<GadgetAuthMessagesComponent>, @Inject(MAT_DIALOG_DATA) public message: string){ }
现在转到模块 .ts 并检查导入
import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from '@angular/material/dialog';
在module.ts中我们需要将MatDialogModule名称放在imports数组下
MatDialogModule
现在终于完成了,我们必须更新提供程序数组
providers:
[{
provide: 'gadget-mlt',
useValue: GadgetMltComponent,
},
{provide:MatDialogRef , useValue:{} },
{ provide: MAT_DIALOG_DATA, useValue: {} }
],
现在它应该可以工作了,希望这对某人有帮助!
只需在 dialogRef 声明之前添加 @Optional()
。
例如:
constructor(
@Optional() public dialogRef: MatDialogRef<yourDialogComponentName>
) {
}
component.ts 和 spec.ts 中的导入路径必须相同
例如:
// in the component and spec files
import { MatDialogRef } from '@angular/material/dialog';
或
// in the component and spec files
import { MatDialogRef } from '@angular/material';
显然我的代码一切正常。问题在于,在开发过程中,我的模态组件有一个时间路径,因此我可以像查看任何其他常规组件一样查看它 component/view。在组件中,我有一个按钮可以触发打开 本身 模式,所以我可以测试它实际打开时的外观。
所以我将打开对话框的代码移到了另一个组件,它似乎解决了问题。
in angular 12 在注入垫对话框之前使用“@Optional()”,如下所示:
@Optional() @Inject(MAT_DIALOG_DATA) public data:any
并在主应用程序模块中添加了如下代码:
providers: [
{
provide: MatDialogRef,
useValue: {}
}
],
最好的问候。
这个错误一般是因为没有提供需要的模块造成的。将外部模块导入到您使用外部模块组件的模块中。这可能会解决问题。
我无法按照文档中的描述注入 MatDialogRef:https://material.angular.io/components/dialog/overview
当我尝试这样做时出现错误:
错误错误:StaticInjectorError[MatDialogRef]: StaticInjectorError [MatDialogRef]: NullInjectorError:没有 MatDialogRef 的提供者!
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import {
MatInputModule,
MatDialogModule,
MatProgressSpinnerModule,
MatButtonModule,
MatDialog,
MatDialogRef
} from '@angular/material';
import { ApiModule } from '../api/api.module';
import { RoutingModule } from '../routing/routing.module';
import { RegistrationComponent } from './components/registration.component';
import { LoginComponent } from './components/login.component';
import { AccountService } from './services/account.service';
@NgModule({
imports: [
BrowserModule,
MatInputModule,
MatDialogModule,
MatProgressSpinnerModule,
MatButtonModule,
FormsModule,
RoutingModule,
ApiModule
],
declarations: [
RegistrationComponent,
LoginComponent
],
entryComponents: [
LoginComponent,
RegistrationComponent
],
providers: [
AccountService,
MatDialog,
MatDialogRef
]
})
export class AccountModule {}
home.component.ts
import { Component } from '@angular/core';
import { MatDialog } from '@angular/material';
import { RegistrationComponent } from '../account/components/registration.component';
@Component({
moduleId: module.id.replace('compiled', 'app'),
templateUrl: 'home.component.html'
})
export class HomeComponent
{
constructor(private modalService: MatDialog) {}
public openModal() : void
{
let dialog = this.modalService.open(RegistrationComponent, {});
}
}
registration.component.ts
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { MatDialogRef } from '@angular/material/dialog';
import { User } from '../../../models/domain/User';
import { ApiUserService } from '../../api/entity-services/user.service';
import { AuthService } from '../../auth/auth.service';
import { AccountService } from '../services/account.service'
@Component({
selector: 'registration-component',
templateUrl: 'app/modules/account/templates/registration.component.html'
})
export class RegistrationComponent
{
public user :User = new User();
public errorMessage :string;
public isLoading :boolean;
constructor
(
private userService :ApiUserService,
private authService :AuthService,
private accountService :AccountService,
private router :Router,
public dialogRef :MatDialogRef<RegistrationComponent>
)
{
this.isLoading = false;
}
public onSubmit(e) :void
{
e.preventDefault();
this.isLoading = true;
this.userService
.Create(this.user)
.subscribe(
user =>
{
this.user.id = user.id;
this.user.login = user.login;
this.authService
.Login(this.user)
.subscribe(
token =>
{
this.accountService.Load()
.subscribe(
account =>
{
this.user = account;
this.isLoading = false;
this.dialogRef.close();
let redirectRoute = account.activeScopeId
? `/scope/${account.activeScopeId}`
: '/scope-list/';
this.router.navigate([redirectRoute]);
},
error => this.errorMessage = <any>error
);
},
error => this.errorMessage = <any>error
);
},
error => this.errorMessage = <any>error
);
}
}
这可能是因为您没有包含 Angular 动画工作所需的 Web 动画 API polyfill,因为它依赖于 API.
这里是 caniuse 适用于本机支持它的浏览器。目前只有 Chrome、Firefox 和 Opera 支持 Web Animations API。
无论如何,您必须按照以下步骤来获得 polyfill:
在终端中,在您的控制台中输入以下内容:
npm install web-animations-js
安装完成后,取消注释
polyfills.ts
中 Angular Animations 的行(如果不存在则添加):import 'web-animations-js'; // Uncomment this line
或者,您可以尝试从单独的端点导入模块,如下所示:
发件人:
import { MatButtonModule, MatDialogModule } from '@angular/material';
收件人:
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
感谢@Edric,我通过从 @angular/material/dialog
而不是 @angular/material
导入 MatDialogModule
、MatDialog
和 MatDialogRef
解决了这个问题
- 在您的模块中:仅从 angular/material 导入 MatDialogModule 就足够了。不需要导入和提供:MatDialogRef
- 在你的代码中 DialogComponent
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material';
- 以上是我遵循的步骤。不确定为什么需要从对话框中导入它
- 但是,能否说明一下您在 html/template 中使用的选择器?如果您在模板中使用了 "registration-component",这可能就是您会收到此错误的原因。我从 Material 指南中尝试了完全相同的示例。我不小心用了 'dialog-overview-example-dialog' 而不是 'dialog-overview-example'。 = 我遇到了和你一样的错误。
我在向要在多个组件中共享的服务添加对话框时遇到此错误。只是为了澄清,在将对话框移动到服务之前,应用程序中不存在错误。解决方案是在主模块
中包含自定义提供程序MatDialogRef
import { DialogService } from './services/dialog.service';
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
...
imports: [
...
MatDialogModule
],
providers: [
{
provide: MatDialogRef,
useValue: {}
},
DialogService
],
...
有了这个提供者,服务作为一个单例工作,我的对话框被共享,并且提供者错误消失了。
此错误可能是由于在调用 MatDialog::open 的组件中注入 MatDialogRef
而不是在传递给 open 方法的组件中造成的。传递给 MatDialog open 方法的组件应该像 the example.
MatDialogRef
@Component({
selector: 'dialog-overview-example-dialog',
templateUrl: 'dialog-overview-example-dialog.html',
})
export class DialogOverviewExampleDialog {
constructor(
public dialogRef: MatDialogRef<DialogOverviewExampleDialog>,
@Inject(MAT_DIALOG_DATA) public data: DialogData) {}
onNoClick(): void {
this.dialogRef.close();
}
}
对我来说,问题是我将我的对话框组件添加到其他一些 HTML 模板只是为了测试它。一旦我删除它,OP 中的错误就消失了,它就起作用了。
例如您正在使用 app-checkout
如果您在 'dialog' 和 'normal' 中使用一个组件,则可能会在正常 html 文件中添加 app-checkout
。
解决方案 1:
删除 <app-checkout> </app-checkout>
如果您不需要以正常方式将其导入 html 文件
解决方案 2 在对话框和 html 文件中使用。而不是这个:
// ... something have selector: "app-checkout",
constructor(
public dialogRef: MatDialogRef<CheckoutComponent>,
@Inject(MAT_DIALOG_DATA) public dialogData: any
) {}
你需要注入它(使其成为可选注入):
这样:
constructor(
// only need the @Optional() before the public dialogRef
@Optional() public dialogRef: MatDialogRef<CheckoutComponent>,
@Inject(MAT_DIALOG_DATA) public dialogData: any
) {
}
或者这样:
// ... the same above
private dialogRef = null;
private dialogData;
constructor(private injector: Injector) {
this.dialogRef = this.injector.get(MatDialogRef, null);
this.dialogData = this.injector.get(MAT_DIALOG_DATA, null);
}
从构造函数中删除 dialogRef:
https://stackblitz.com/edit/angular-dialog-update?file=src%2Fapp%2Fapp.component.ts
除上述所有情况外,如果您在应用的任何模板文件中引用了组件选择器,您也可能会遇到此错误。 MatDialog 组件只能由 MatDialog.dialog.open() 方法调用,而不是通过组件选择器
不幸的是,由于多种原因,可能会抛出相同的错误消息。
我遇到了这个错误并修复了它你需要做的是
检查你是否像这样在 typescript 文件中插入了 import 语句
从“@angular/material/dialog”导入 {MAT_DIALOG_DATA, MatDialogRef};
检查构造函数
constructor(@Optional() public dialogRef: MatDialogRef<GadgetAuthMessagesComponent>, @Inject(MAT_DIALOG_DATA) public message: string){ }
现在转到模块 .ts 并检查导入
import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from '@angular/material/dialog';
在module.ts中我们需要将MatDialogModule名称放在imports数组下
MatDialogModule
现在终于完成了,我们必须更新提供程序数组
providers:
[{
provide: 'gadget-mlt',
useValue: GadgetMltComponent,
},
{provide:MatDialogRef , useValue:{} },
{ provide: MAT_DIALOG_DATA, useValue: {} }
],
现在它应该可以工作了,希望这对某人有帮助!
只需在 dialogRef 声明之前添加 @Optional()
。
例如:
constructor(
@Optional() public dialogRef: MatDialogRef<yourDialogComponentName>
) {
}
component.ts 和 spec.ts 中的导入路径必须相同
例如:
// in the component and spec files
import { MatDialogRef } from '@angular/material/dialog';
或
// in the component and spec files
import { MatDialogRef } from '@angular/material';
显然我的代码一切正常。问题在于,在开发过程中,我的模态组件有一个时间路径,因此我可以像查看任何其他常规组件一样查看它 component/view。在组件中,我有一个按钮可以触发打开 本身 模式,所以我可以测试它实际打开时的外观。
所以我将打开对话框的代码移到了另一个组件,它似乎解决了问题。
in angular 12 在注入垫对话框之前使用“@Optional()”,如下所示:
@Optional() @Inject(MAT_DIALOG_DATA) public data:any
并在主应用程序模块中添加了如下代码:
providers: [
{
provide: MatDialogRef,
useValue: {}
}
],
最好的问候。
这个错误一般是因为没有提供需要的模块造成的。将外部模块导入到您使用外部模块组件的模块中。这可能会解决问题。