Search code examples
angularangular-material

MAT_DIALOG_DATA: Error: inject() must be called from an injection context Error: inject() must be called from an injection context


I've made a basic modal dialog from the tutorials and am a bit stuck, loading my project serves me this error:

ERROR Error: Uncaught (in promise): Error: inject() must be called from an injection context
Error: inject() must be called from an injection context
    at injectInjectorOnly (core.js:728)

I'm not sure why the error message says lowercase-i inject() instead of capital-I @Inject, which i am invoking in the constructor

import { Component, NgModule, OnInit } from '@angular/core';
import { Inject } from '@angular/core';
import { MatDialog, MatDialogRef, MatDialogConfig, MatDialogModule, MAT_DIALOG_DATA } from '@angular/material/dialog';

@Component({
  selector: 'term-component',
  templateUrl: './term.component.html'
})
@NgModule({
  imports: [MatDialog, MatDialogRef, MatDialogConfig, MatDialogModule],
  providers: [{
    provide: MatDialog, useValue: {}
  }]
})

export class TermDialog implements OnInit {
  constructor(
    @Inject(MAT_DIALOG_DATA) private modalData: any,
    public dialogRef: MatDialogRef<TermDialog>
  ) {
    console.log(this.modalData);
  }

  ngOnInit() { alert(''); }

  actionFunction() {
    this.closeModal();
  }

  closeModal() {
    this.dialogRef.close();
  }

  onNoClick(): void {
    this.dialogRef.close();
  }
}

all the similar help topics say to ensure that I am using capital-I @Inject instead of inject, which I am doing. However, i did see one suggestion to import Inject from '@angular/core/testing' instead of '@angular/core', which I do not think is possible?

Any help would be appreciated, I've never gotten stuck so many times on a Hello World project before.

NEW:

okay so I think I have fulfilled all 5 requirements but I am still seeing the same error. this is my app.module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { RouterModule } from '@angular/router';
import { OverlayModule } from '@angular/cdk/overlay';
import { MatDialogModule } from '@angular/material/dialog';
import { AmplifyAngularModule, AmplifyService } from 'aws-amplify-angular';

import { AppComponent } from './app.component';
import { NavMenuComponent } from './nav-menu/nav-menu.component';
import { HomeComponent } from './home/home.component';
import { CounterComponent } from './counter/counter.component';
import { FetchDataComponent } from './fetch-data/fetch-data.component';

import { TermComponent } from './term.component';
import { TermDialog } from './term-dialog.component';
import { LoginComponent } from './login/login.component';

@NgModule({
  declarations: [
    AppComponent,
    NavMenuComponent,
    HomeComponent,
    CounterComponent,
    FetchDataComponent,
    TermComponent,
    LoginComponent,
    TermDialog
  ],
  imports: [
    AmplifyAngularModule,
    BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
    HttpClientModule,
    FormsModule,
    OverlayModule,
    MatDialogModule,
    RouterModule.forRoot([
      { path: '', redirectTo: '/login', pathMatch: 'full' },
      { path: 'login', component: LoginComponent },
      { path: 'counter', component: CounterComponent },
      { path: 'fetch-data', component: FetchDataComponent },
      { path: 'term', component: TermComponent },
      { path: '**', component: LoginComponent }
    ])
  ],
  entryComponents: [
    TermDialog
  ],
  providers: [
    AmplifyService
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

and my term.component file that is supposed to launch the term-dialog

import { Component, NgModule } from '@angular/core';
import { MatDialog, MatDialogConfig, MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { TermService } from '../../services/term.service';
import { TermDialog } from './term-dialog.component';
import { compileNgModule } from '@angular/compiler';

@Component({
  selector: 'term-component',
  templateUrl: './term.component.html'
})
@NgModule({
  imports: [MatDialogModule],
  providers: [{ provide: MatDialog, useValue: {} 
  }]
})
export class TermComponent {
  clicked: boolean;
  success: boolean;

  constructor(public dialog: MatDialog, private termService: TermService) {

    this.clicked = false;
  }

  openAddNewTermDialog() {

    const dialogConfig = new MatDialogConfig();
    dialogConfig.disableClose = true;
    dialogConfig.height = "350px";
    dialogConfig.width = "600px";
    dialogConfig.data = {
    };

    const dialogRef = this.dialog.open(TermDialog, dialogConfig);
    dialogRef.afterClosed().subscribe(result => {
      console.log('closed dialog');
      this.success = result;
    })
  }
}

Solution

  • Alright so turns out the answer was just to not use MatDialogs at all, and just simply inject the TermDialogComponent html into the basic modal dialog using the TermDialogComponent's selector tag

    So i added html for a modal dialog into my term.component.html and simply pasted in

    <term-dialog-component></term-dialog-component>
    

    and everything worked as intended with no fuss, added modules/librarys whatsoever. I may never know why I couldn't get a basic modal MatDialog to work properly, but I've made my peace with that. My advice for anyone with this same problem is to not use MatDialogs, it isn't worth it and also the weird tab animations look funny anyway.

    thanks to everyone for their responses and time