Error caused by a null injector when sharing an Angular module that contains different @angular/material modules

My uiModule is set up to import and export various @angular/material modules.

I was expecting that by importing uiModule into anotherModule, anotherModule would have access to the @angular/material components. However, this doesn't seem to be working as intended.

While the material components work fine within the uiModule, anotherModule recognizes them but throws errors such as:

NullInjectorError: No provider for InjectionToken mat-menu-scroll-strategy!

NullInjectorError: No provider for Overlay!

These errors occurred when trying to use <mat-menu>

This is how the uiModule looks like:

// material imports
import { MatExpansionModule } from '@angular/material/expansion';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatChipsModule } from '@angular/material/chips';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatNativeDateModule } from '@angular/material/core';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatDialogModule } from '@angular/material/dialog';

const material = [
  MatIconModule,
  MatProgressSpinnerModule,
  MatProgressBarModule,
  MatExpansionModule,
  MatInputModule,
  MatChipsModule,
  MatAutocompleteModule,
  MatFormFieldModule,
  MatDatepickerModule,
  MatNativeDateModule,
  MatMenuModule,
  OverlayModule,
  MatDialogModule,
  ScrollingModule,
];

@NgModule({
  declarations: [
    PaginationComponent,
  ],
  imports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    ...material,
  ],
  providers: [],
  exports: [
    PaginationComponent,
    ...material,
  ],
})

Answer №1

The patterns of errors you are encountering all point to issues with providers! It seems like there are some missing providers in the location where you are utilizing a material component. One example is the Overlay Provider.

It's important to understand that the way components and services function can vary.

You can incorporate a component (A) from one module (B) by exporting component A in its module A and importing the module of the component in B. This step must be repeated in every module that intends to use component A.

If module A requires a service, it can be provided at either the module level or the root level. Failure to provide this can result in an error.

Since no code showcasing the usage of material components causing errors has been shared, let me illustrate a scenario where such errors could arise.

Scenario: anotherModule contains a component with a button in its HTML that triggers a dialog.

Dialog components are not rendered within the opening component and have access to the injector of anotherModule. Therefore, even if you imported uiModule into materialModule, not importing it into AppModule may lead to "No provider for XYZ" errors.

To resolve this issue, consider importing uiModule into AppModule.

Answer №2

When creating a module that exports all necessary material components, simply import and export the required material modules within that module.

Modify the MaterialModule as shown below:

import { NgModule } from '@angular/core';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
// Add other material modules here

@NgModule({
  imports: [
    // Add imported material modules here
  ],
  exports: [
    // Add exported material modules here
  ],
})
export class MaterialModule {}

Then include this in your uiModule where you defined the PaginationComponent or in any appropriate location.


If you wish to utilize lazyLoading effectively, it is recommended to import each module only where it is needed. This approach can enhance the loading performance of your application by avoiding unnecessary module loading.

You can improve user experience by implementing the following code in app-routing.module.ts:

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    preloadingStrategy: PreloadAllModules
  })],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Answer №3

Upon reviewing the code you provided, everything seems to be in order with the concept you described. The material modules should indeed be accessible to the importing module.

The only issue I noticed is that there are two imports missing in your ui.module.ts file:

import {ScrollingModule} from '@angular/cdk/scrolling';
import {OverlayModule} from '@angular/cdk/overlay';

Once you add these imports, I recommend running the command npm install to ensure all dependencies are properly installed. This should resolve any issues with the code.

If you encounter any further problems, please don't hesitate to reach out for assistance.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Run the function on multiple occasions

I am attempting to execute the function independently for each .item1 and .item2, among others. How can I ensure that the function runs for any nth number of instances on a given page? $("#edit-toggle").prop("checked", true); $(".edit :input").attr("di ...

Send multiple values as arguments to a jQuery function

Beginner question ahead: I'm using the jquery function loadNewPicture() to upload pictures and the progress() function to track the percentage of the upload. Everything is functioning correctly. My query relates to the variables that can be passed t ...

"Implementing an Angular route component that adjusts based on specific

I am currently working on routing within my application for the 'feed' module. Within this feed, there are two types of posts that I need to display with a direct link to show full information. How can I ensure that the right component is opened ...

Why won't my second div with the unordered list show up?

I am currently working on developing a To-Do list application, and I have encountered an issue with the second div that contains an unordered list. The list is not displaying, and I am unsure of the reason behind this. I attempted to remove the div and a ...

Display a visual progress indicator during audio recording

I am currently using the MediaRecorder functionality to capture audio and I would like to display a progress bar showing the recording process. Here is the code snippet from my recorder template: <p id="countdowntimer">Current Status: Beginning in& ...

Search through an array of objects that contains nested arrays of objects with various property names and values

I have an Array of objects structured like this: [{ property1: 'test', property2: 'test', filter: [{ fil1: 1, fil2: 2, fil3: 3 }, { fil1: 56, fil2: 3, fil3: 34 ...

Unlawful manipulation of filtering in typescript

My task involves sifting through an array of objects to separate them based on their status codes. If the item has a status code of 1, I store it in the openIssue array; if it has a status code of 3, it goes into the inProgressIssue array. This is the rel ...

Incorporating user input into the dynamic creation process of an Angular 2 component using ComponentResolver

After successfully loading a dynamic Angular 2 component using ComponentResolver and ViewContainerRef, I am faced with the challenge of passing input variables from the parent component to the child component. parent.ts @Component({ selector: "parent", ...

Dealing with missing URL parameters in Express.js

I'm struggling with handling a null URL parameter in my web services assignment. The current code I have written is as follows: app.get('/nachos/:x/:cheese/:tomatoes/:salsa/:hotsauce', (req, res) => { var x = parseInt(req.par ...

What is the best way to export Firebase admin in Typescript?

Struggling to export Firebase admin for access in my modules while using Typescript. Upon importing it into my modules, the properties of admin are not recognized. admin.ts import * as admin from "firebase-admin"; admin.initializeApp(); module. ...

Help needed with jQuery to load a value from a text file and display it in a dropdown menu, then retrieve the user's selection - seeking

Greetings, fellow coders. I'm reaching out to the community for some assistance :) Currently, I have a PHP form with three dropdown menus that utilizes a jQuery function to load .txt files and generate two dynamic dropdown menus based on the selectio ...

What is the best way to stack a canvas box on top of another canvas box?

My goal is to have two canvas squares stacked on top of each other. While I am familiar with drawing on canvas, I need assistance in placing one canvas on top of another. Despite my attempts at setting the position, I have not been successful. <canvas ...

What is the method for accessing HTML tag data within a script?

Looking for a way to extract a specific substring from a given string: var str = `<ul class="errorlist"><li>Enter a valid email address.</li></ul>`; Is there a method to extract the following substring? 'Enter a valid email ...

select items using a dropdown menu in an Angular application

Let me describe a scenario where I am facing an issue. I have created an HTML table with certain elements and a drop-down list Click here for image illustration When the user selects in, only records with type in should be displayed Another image refere ...

Exploring Angular: How to access ViewChild from a dynamically loaded component

One of my components includes a ViewChild element like this: @ViewChild('overView') content: ElementRef; I am dynamically loading this component in the following way: let overviewComponent = this.vcr.createComponent(OverviewComponent); let conte ...

Deleting the Last Node in a Linked List

My current project involves creating a function that removes the last node of a given list passed in as an argument. The function itself is relatively simple and is shown below. function popBack(list) { var current = list.head, previous; ...

Is there a way to delegate the operation of Object3d.toJSON() to a web worker for optimization?

Is there a way to efficiently convert the active scene in threejs to a JSON object? The process seems to slow down as the models get larger, making it difficult to show a progress bar. I attempted sending the threejs scene to a web worker for conversion, ...

Issue: The system is unable to locate the "moduleIntro.js" module while executing the "http" command

I recently embarked on a journey to learn Node.js and decided to experiment with the 'http' module. Here is a snippet of the code I tried to run: var http = require('http'); http.createServer(function (req, res) { res.write('H ...

Loading a view in Ionic2 with Angular2 after a successful subscription

After completing an http post request, I want to navigate to the next view in my app. Here is a breakdown of the three services I am using: The server service handles generic http calls such as get and post requests. The city service stores a list of ...

Including a 3DS card to a Stripe Client for recurring payments

I'm encountering an issue when trying to add payment cards with 3DS authentication for existing customers who already have an active monthly subscription. The objective is to allow our clients to change, remove, and add cards to the Stripe Customer ob ...