Repository navigation
Description
I upgraded my project from Angular 8 to 9 and refactored my code to take advantage of the ability to lazy load components. For most of my components this works great, but I have one that is throwing an error and I need help resolving the issue.
Here is my component code followed by the error. The module is defined in the same file as the component.
import { Component, OnInit, OnDestroy, NgModule } from '@angular/core';
import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { switchMap, debounceTime, tap, filter } from 'rxjs/operators';
import { MatFormFieldModule, MatInputModule, MatAutocompleteModule, MatButtonModule, MatProgressSpinnerModule, MatIconModule, MatDialogModule } from '@angular/material';
import { SearchService } from './search.service';
import { SuggestResult } from './suggest-result';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { SharedModule } from 'src/app/shared/shared.module';
@Component({
selector: 'app-search',
templateUrl: './search.component.html',
styleUrls: ['./search.component.scss'],
providers: [ FormBuilder]
})
export class SearchComponent implements OnInit, OnDestroy {
//code removed
}
@NgModule({
imports: [
CommonModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
MatFormFieldModule,
MatInputModule,
MatAutocompleteModule,
MatButtonModule,
MatProgressSpinnerModule,
MatIconModule,
SharedModule,
MatDialogModule
],
declarations: [SearchComponent]
})
export class SearchModule { }<div>
<div class="form-container">
<form [formGroup]='resultsForm'>
<mat-form-field [class.mat-form-field-invalid]="!formFieldValid">
<input matInput placeholder="Search term" type="search" [matAutocomplete]="SearchAuto" formControlName='SearchUserInput'>
</mat-form-field>
<div *ngIf="!formFieldValid" class="error-msg"> {{ errorMessage }} </div>
<mat-autocomplete #SearchAuto="matAutocomplete" [displayWith]="getSelectedText"
(optionSelected)='onItemSelected($event.option.value)'>
<mat-option *ngIf="isLoading" class="is-loading">
<mat-spinner mode="indeterminate" diameter="25"></mat-spinner>
</mat-option>
<ng-container *ngIf="!isLoading">
<mat-option *ngFor="let result of filteredResults" [value]="result">
<span>{{ result.name }}</span>
</mat-option>
</ng-container>
</mat-autocomplete>
</form>
<mat-icon>search</mat-icon>
<button mat-button *ngIf="isNotEmpty()" matSuffix mat-icon-button aria-label="Clear" (click)="clearSearch()">
<mat-icon>close</mat-icon>
</button>
</div>
</div>The error:
null: Error: Uncaught (in promise): NullInjectorError: R3InjectorError(AppModule)[InjectionToken mat-autocomplete-scroll-strategy -> InjectionToken mat-autocomplete-scroll-strategy -> InjectionToken mat-autocomplete-scroll-strategy]:
NullInjectorError: No provider for InjectionToken mat-autocomplete-scroll-strategy!
./node_modules/@angular/core/ivy_ngcc/fesm5/core.js/NullInjector.prototype.get@http://localhost:4200/vendor.js:37066:25
./node_modules/@angular/core/ivy_ngcc/fesm5/core.js/R3Injector.prototype.get@http://localhost:4200/vendor.js:47422:33
./node_modules/@angular/core/ivy_ngcc/fesm5/core.js/R3Injector.prototype.get@http://localhost:4200/vendor.js:47422:33
./node_modules/@angular/core/ivy_ngcc/fesm5/core.js/R3Injector.prototype.get@http://localhost:4200/vendor.js:47422:33
./node_modules/@angular/core/ivy_ngcc/fesm5/core.js/NgModuleRef$1.prototype.get@http://localhost:4200/vendor.js:60382:33
get@http://localhost:4200/vendor.js:58703:35
getOrCreateInjectable@http://localhost:4200/vendor.js:39763:39
ɵɵdirectiveInject@http://localhost:4200/vendor.js:50290:12
MatAutocompleteTrigger_Factory@http://localhost:4200/vendor.js:76965:788
getNodeInjectable@http://localhost:4200/vendor.js:39871:44
searchTokensOnInjector@http://localhost:4200/vendor.js:39807:16
getOrCreateInjectable@http://localhost:4200/vendor.js:39729:58
ɵɵdirectiveInject@http://localhost:4200/vendor.js:50290:12
ɵɵinject@http://localhost:4200/vendor.js:36956:57
factory@http://localhost:4200/vendor.js:47681:44
multiResolve@http://localhost:4200/vendor.js:55407:21
multiProvidersFactoryResolver@http://localhost:4200/vendor.js:55372:12
getNodeInjectable@http://localhost:4200/vendor.js:39871:44
searchTokensOnInjector@http://localhost:4200/vendor.js:39807:16
getOrCreateInjectable@http://localhost:4200/vendor.js:39729:58
ɵɵdirectiveInject@http://localhost:4200/vendor.js:50290:12
FormControlName_Factory@http://localhost:4200/vendor.js:74579:400
getNodeInjectable@http://localhost:4200/vendor.js:39871:44
searchTokensOnInjector@http://localhost:4200/vendor.js:39807:16
getOrCreateInjectable@http://localhost:4200/vendor.js:39729:58
ɵɵdirectiveInject@http://localhost:4200/vendor.js:50290:12
ɵɵinject@http://localhost:4200/vendor.js:36956:57
factory@http://localhost:4200/vendor.js:47681:44
getNodeInjectable@http://localhost:4200/vendor.js:39871:44
searchTokensOnInjector@http://localhost:4200/vendor.js:39807:16
getOrCreateInjectable@http://localhost:4200/vendor.js:39729:58
ɵɵdirectiveInject@http://localhost:4200/vendor.js:50290:12
MatInput_Factory@http://localhost:4200/vendor.js:99837:370
getNodeInjectable@http://localhost:4200/vendor.js:39871:44
instantiateAllDirectives@http://localhost:4200/vendor.js:44362:42
createDirectivesInstances@http://localhost:4200/vendor.js:43753:29
ɵɵelementStart@http://localhost:4200/vendor.js:50436:34
ɵɵelement@http://localhost:4200/vendor.js:50487:19
SearchComponent_Template@http://localhost:4200/search-search-search-component.js:190:56
executeTemplate@http://localhost:4200/vendor.js:43726:19
renderView@http://localhost:4200/vendor.js:43551:28
renderComponent@http://localhost:4200/vendor.js:44741:15
renderChildComponents@http://localhost:4200/vendor.js:43412:24
renderView@http://localhost:4200/vendor.js:43576:34
./node_modules/@angular/core/ivy_ngcc/fesm5/core.js/ComponentFactory.prototype.create@http://localhost:4200/vendor.js:58804:23
createContainerRef/R3ViewContainerRef</ViewContainerRef.prototype.createComponent@http://localhost:4200/vendor.js:46481:53
./src/app/dynamic-loader/dynamic-loader.service.ts/DynamicLoaderService.prototype.addComponentToContainer/obs<@http://localhost:4200/main.js:583:23
./node_modules/zone.js/dist/zone.js/</Zone$1</ZoneDelegate</ZoneDelegate.prototype.invoke@http://localhost:4200/polyfills.js:2740:30
onInvoke@http://localhost:4200/vendor.js:63629:33
./node_modules/zone.js/dist/zone.js/</Zone$1</ZoneDelegate</ZoneDelegate.prototype.invoke@http://localhost:4200/polyfills.js:2739:36
./node_modules/zone.js/dist/zone.js/</Zone$1</Zone</Zone.prototype.run@http://localhost:4200/polyfills.js:2497:47
scheduleResolveOrReject/<@http://localhost:4200/polyfills.js:3238:38
./node_modules/zone.js/dist/zone.js/</Zone$1</ZoneDelegate</ZoneDelegate.prototype.invokeTask@http://localhost:4200/polyfills.js:2775:35
onInvokeTask@http://localhost:4200/vendor.js:63617:33
./node_modules/zone.js/dist/zone.js/</Zone$1</ZoneDelegate</ZoneDelegate.prototype.invokeTask@http://localhost:4200/polyfills.js:2774:40
./node_modules/zone.js/dist/zone.js/</Zone$1</Zone</Zone.prototype.runTask@http://localhost:4200/polyfills.js:2542:51
drainMicroTaskQueue@http://localhost:4200/polyfills.js:2955:39
Activity
kara commentedon Feb 28, 2020
@schinks Can you create a minimal repro on ng-run or Stackblitz? In it's current state, the snippet is too large to be actionable by the team.
schinks commentedon Feb 28, 2020
Is it possible to create a stackBlitz using Angular 9 and Material?
schinks commentedon Feb 28, 2020
I see that ng-run defaults to 9 so I'll give that a try. Thanks.
schinks commentedon Mar 2, 2020
@kara I am having problems using stackBlitz (can't get ng 9) and ng-run is giving an error after installing material. Can I just create a github repo for you to use?
pkozlowski-opensource commentedon Mar 3, 2020
@schinks if you've got troubles using stackblitz, you could try https://ng-run.com/. GitHub repo is more problematic (takes us more time to understand what is going on) but would be OK if you can't reproduce it otherwise.
In any case please try to keep the reproduce scenario to the absolute minimum...
schinks commentedon Mar 3, 2020
I got ng-run to work and the error is being thrown there. Run the app and click the search button, the error should be in F12. ng-run project Note the comment in the template file for search component.
bollerdominik commentedon Mar 14, 2020
I am also having this exact issue when having a lazy loaded module with MatAutocomplete
21 remaining items
AshMcConnell commentedon Oct 7, 2020
@JoostK Thanks for your explanation, it helped me a lot. I seem to be having problems getting it to work in production mode. I have included
"src/app/**/*.component.ts",in the tsconfig.app.json, but I still get this error when I useng serve --prod(only to test)Error: C:\Dev\bucardo-web\src\app\+enquiries\enquiries.component.ts is missing from the TypeScript compilation. Please make sure it is in your tsconfig via the 'files' or 'include' property. at AngularCompilerPlugin.getCompiledFile (C:\Dev\bucardo-web\node_modules\@ngtools\webpack\src\angular_compiler_plugin.js:933:23)Do you know what I might have done wrong?
Thanks!
JoostK commentedon Oct 7, 2020
@AshMcConnell sorry, that doesn't ring a bell. It might be that
src/app/**/*.component.tsis resolved against a base url that starts atsrc, so you may want to tryapp/**/*.component.ts? I don't know the logic in the CLI'sAngularCompilerPluginto give you a better hint at the moment.AshMcConnell commentedon Oct 7, 2020
Thanks @JoostK I'll give it a go. Odd that it works in non-production mode though
tomasdev commentedon Oct 8, 2020
MatTooltipModulealso throwsERROR Error: NullInjectorError: No provider for InjectionToken mat-tooltip-scroll-strategy!The fix was the same as before, to import
MatTooltipModulein the App-level module, and not inside a sub-component. The isolated case in StackBlitz works fine though https://stackblitz.com/edit/angular-nw6rvlcsbenjamin commentedon Nov 30, 2020
@JoostK Thanks for your solution.
As you said, the code given will create a new instance of the module each time. And we can solve this easily creating a cache. I have a module, say
FeatureModule, that I would like to use inloadChildrenof theRoutermodule. Also I would like to use a lazy loadedFeatureComponentin another module. It turns out thatFeatureComponentis declared inFeatureModuleand depends on a service that it provides. So, I use your solution to load theFeatureModuleand to create theFeatureComponent. But if latter on, I navigate to a url which loads theFeatureModulelazily, then I will have two instances of theFeatureModule, one in my custom cache and another in theRoutercache. Is there a way to use theRoutercache instead my custom cache to avoid having two instances of theFeatureModule?barnabasbartha commentedon Jul 9, 2021
The fix was the same as before, to import MatTooltipModule in the App-level module, and not inside a sub-component.Is there a way to avoid importing it into the AppModule but to the lazy loaded modules where needed?
parys commentedon Jan 29, 2022
Any news? Issue relates to any module/provider that is was not imported before lazy module. This issue forces me to Import miss modules and Providers to app level, so lazy loading is losing sense because of I have already imported all heavy staff to app level.
devashishSarmah commentedon Feb 18, 2022
I was struggling with the same issue.
providing
MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY_PROVIDERandMAT_SELECT_SCROLL_STRATEGY_PROVIDERin the component level solved it for me.jessicajaniuk commentedon Apr 27, 2022
This is working as designed, but with a bit of a design flaw. This is mitigated in standalone components, but of course would require the effort to make your app use standalone components. The workaround is to import the ngmodule or to use the ngModuleRef of the module so that it's included in your module dependency graph.
angular-automatic-lock-bot commentedon May 28, 2022
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.