Renderer cannot be used in Service?

2020-03-01 05:51发布

问题:

Is it possible to use Renderer in Service or just in component?

If I inject renderer into service I get error, that the Renderer provider is missing.

See plunker's console:

import {Injectable, Component, Renderer, ElementRef} from 'angular2/core';

@Injectable()
class TestService {
  constructor(
    private _renderer: Renderer
    ) {}

  renderElement(elementRef: any) {
    this._renderer.createElement(elementRef.nativeElement, 'div');
  }
}

http://plnkr.co/edit/e8qlznCVbvZnXbLTk36z?p=preview

回答1:

Yea, like Eric said you can just pass it from the actual component to the Service and it will work.

HOWEVER, the responsability to render an object is of the component, not the Service, services are meant to handle business logic (retrieve the data mostly, depending on your app).

The whole idea is that you can reuse your whole services layer if you ever change your presentation framework/library or anything presentation related stuff at all, If you do things like that you'd be coupling your services to your presentation, making harder to make changes later on.

If you want to reuse the rendering logic between components, I'd create a parent abstract class with the logic and extend it with a Component, the children component would get injected the renderer and pass it to the parent class with the super() method that should call the parent's constructor.

At the very least you can make an @Injectable object like the proposed solution, but call it SomethingRenderer instead of Service and separate it from the rest of your real Data Services.



回答2:

Possibly duplicating with Using Renderer in Angular 4

You cannot inject Renderer2, but we can run RendererFactory2 to get Renderer2 instance inside @Injectable() service. There are two different ways of solving this issue.

Get an instance of Renderer2 inside Service

There is the way which Angular using internally in webworkers, for example. I've solved the problem with the code below:

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

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

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

Parameters of RendererFactory2.createRenderer method are:

  • hostElement with type any
  • type with type RendererType2|null

You can see that (null, null) parameters are here: https://github.com/angular/angular/blob/e3140ae888ac4037a5f119efaec7b1eaf8726286/packages/core/src/render/api.ts#L129

Pass Renderer2 from component

// 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;
  }
}


标签: angular