Reputation: 1826
Using Angular 5, I am firing a function, select()
from one component only for selection that triggers another function, getqr()
in another component for printing. getqr()
fires a web request for items that are selected from the first component. In order to update the print view to reflect the request, I am using ChangeDetectorRef
. Doing this gives me an error of:
StaticInjectorError(AppModule)[PrintComponent -> ChangeDetectorRef]:
StaticInjectorError(Platform: core)[PrintComponent -> ChangeDetectorRef]: NullInjectorError: No provider for ChangeDetectorRef!
I'm not sure what the issue is here as I cannot (and should not have to) add ChangeDetectorRef
to providers
in app.module.ts.
Here is the TS for the selection component:
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { PrintComponent } from './print/print.component';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
docs;
constructor(public http: HttpClient, public print: PrintComponent) { }
ngOnInit() {
this.http.get("https://portal.oldnational.com/corporate/portalsupport/_api/web/lists/getbytitle('Document Separator Barcodes')/items?$top=1000&$orderBy=DocumentGroup,Title").subscribe(data => {
this.docs = data['value'];
});
}
select(ID, selected){
if (selected == true) {
this.print.selecteddocs.push(ID); //Adds selection to array on Print Component
}
else {
var index = this.print.selecteddocs.indexOf(ID);
this.print.selecteddocs.splice(index, 1); //Removes selection from array on Print Component
}
this.print.getqr(); //fires getqr() from Print Component
}
}
Here is the TS for the print component:
import { Component, OnInit, ChangeDetectorRef} from '@angular/core';
.....
@Component({
selector: 'app-print',
templateUrl: './print.component.html',
styleUrls: ['./print.component.css'],
})
export class PrintComponent implements OnInit {
barcodeitems;
selecteddocs = [];
constructor(public http: HttpClient, private cdr: ChangeDetectorRef){
}
ngOnInit(): void {
}
getqr() {
console.log("selecteddocs array", this.selecteddocs);
let filterQuery = this.selecteddocs.map(i => `ID eq '${i}'`).join(" or ");
let url = `https://portal.oldnational.com/corporate/portalsupport/_api/web/lists/getbytitle('Document Separator Barcodes')/items?$top=1000&$orderBy=ID&$filter=${filterQuery}`
this.http.get(url).subscribe(data => {
console.log("data.value", data['value']); //Correctly logs results
this.barcodeitems = data['value'];
this.cdr.detectChanges(); //Attempt to refresh the view
});
}
}
What can I do to fix this issue or update the view of the Print Component after a selection is made?
Upvotes: 13
Views: 16400
Reputation: 5066
You cannot use something containing ChangeDetectorRef inside services. for example - one of the answers was about translocoPipe - it is impure that's why it uses CD for its triggering. If you use component in constructor - or pipe - you need to provide ChangeDetectorRef for them as well in service, but this is sort of bad practice.
You can use services inside services without problems, but pipes should be used inside the components - where the injection context is provided. Or, you need to make specific provider globally which will have a factory for your pipe for example like here https://github.com/ngx-translate/core/issues/593
Upvotes: 0
Reputation: 386
I run into such situation "NullInjectorError: No provider for ChangeDetectorRef" in Angular 17 application. And it was "flickering" one. When a page was open by link from other page - nothing happens but there is error when the page open by direct link.
The reason was in injected TranslocoDatePipe which is not actually used.
the page was created in Angular 15 and working well.
There is other story with NullInjectorError. In that time it happened only on "ng build". "ng serve" worked well. There was big refactoring included 2 components which become abstract for to be a base for inheriting.
and I spent whole day to found the reason - and it was "styleUrls: ['']".
So Angular 17 brought some surprises.
Upvotes: 2
Reputation: 181
In my case i was calling changeDetectorRef: ChangeDetectorRef
from a service.
it works fine. once changeDetectorRef: ChangeDetectorRef
moved from service to a component.
Do not import ChangeDetectorRef into services
Upvotes: 15
Reputation: 4096
I've solved this by passing the reference to ChangeDetector from the app component,
i.e. change the constructor in app.component.ts
to
constructor(
changeDetectorRef: ChangeDetectorRef,
ms: MobileService) {
ms.setChangeDetector(changeDetectorRef);
}
Upvotes: 1