Service: no provider for Renderer2

Angular 4.2 with Typescript 2.3

I am refactoring a service that is responsible for creating a new script tag and adding it to a document.

Here is the old code:

loadScript(src:string){
    const script = document.createElement('script');
    document.body.appendChild(script);
    script.src = src;
}

Now I would like to use Renderer2to avoid direct manipulation of the DOM. So, I entered what I need in my service and updated the code:

constructor(private renderer:Renderer2, @Inject(DOCUMENT) private document){}

loadScript(src:string){
    const script = this.renderer.createElement('script');
    this.renderer.appendChild(this.document.body,script);
    script.src = src;
}

However, I encounter this error:

Error: no provider for Renderer2!

The service belongs to CommonModule CoreModule, the only import of which is CommonModulefrom@angular/common

This plankre demonstrates the problem.

+16
source share
3 answers

You can initialize the service using an instance Renderer2in the root component

@Injectable()
class MyService {
  renderer : Renderer2;
}
...
class App {
  name:string;
  constructor(service: MyService, renderer: Renderer2) {
      service.renderer = renderer;
  }
}

see also

+13

Renderer Angular 4

Renderer2, RendererFactory2 Renderer2 @Injectable(). .

Renderer2

, Angular , , -. :

import { Renderer2, RendererFactory2 } from '@angular/core';

@Injectable()
class Service {
    private renderer: Renderer2;

    constructor(rendererFactory: RendererFactory2) {
        this.renderer = rendererFactory.createRenderer(null, null);
    }
}

@Injectable()
class Service {
  private renderer: Renderer2;

  constructor(rendererFactory: RendererFactory2, @Inject(DOCUMENT) private document){
    this.renderer = rendererFactory.createRenderer(null, null);
  }

  loadScript(src:string){
    const script = this.renderer.createElement('script');
    this.renderer.appendChild(this.document.body,script);
    script.src = src;
  }
}

RendererFactory2.createRenderer:

  • hostElement any
  • type RendererType2|null

, (null, null) : https://github.com/angular/angular/blob/e3140ae888ac4037a5f119efaec7b1eaf8726286/packages/core/src/render/api.ts#L129

Renderer2

// declare public property in your service
@Injectable()
class Service {
  renderer: Renderer;
}

// pass renderer to service in your component file
class App {
  name:string;
  constructor(service: Service, renderer: Renderer2) {
      service.renderer = renderer;
  }
}
+27

I tried to implement this with render2, but in the service - which led to the "StaticInjectorError (AppModule) [Renderer2]" -Error, since the implementation of Renderer2-Instance seems to be impossible. The solution was to implement RendererFactory2 and manullay to create a link in the service, for example:

@Injectable({
  providedIn: 'root'
})
export class FgRendererService {
  /** Reference to render-instance */
  public renderer: Renderer2;
  /** CONSTRUCTOR */
  constructor(
    private _renderer: RendererFactory2
  ) {
    this.renderer = _renderer.createRenderer(null, null);
  }
  /** Add class to body-tag */
  addBodyClass( classToAdd: string ): void {
    this.renderer.addClass( document.body, classToAdd );
  }
  /** Remove class from body-tag */
  removeBodyClass( classToRemove: string ): void {
    this.renderer.removeClass( document.body, classToRemove );
  }
}
0
source

Source: https://habr.com/ru/post/1681032/


All Articles