cfoster5
cfoster5

Reputation: 1826

NullInjectorError: No provider for ChangeDetectorRef

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

Answers (4)

Igor Kurkov
Igor Kurkov

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

Larest
Larest

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.

enter image description here

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: ['']". enter image description here

So Angular 17 brought some surprises.

Upvotes: 2

Ajmal faiz
Ajmal faiz

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

seaders
seaders

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

Related Questions