Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Renderer cannot be used in Service?

Tags:

angular

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

like image 801
eesdil Avatar asked Jan 10 '16 20:01

eesdil


People also ask

What is renderer service?

Services rendered are the services that a company completes for the client or customer prior to receiving payment for the services. An accountant details the rendered service, or an invoice, at the conclusion of a service agreement and presents it to the client in order to receive payment.

What is the use of renderer in angular?

The Renderer2 class is an abstraction provided by Angular in the form of a service that allows to manipulate elements of your app without having to touch the DOM directly.


2 Answers

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;
  }
}
like image 113
Eugene Gavrilov Avatar answered Oct 20 '22 05:10

Eugene Gavrilov


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.

like image 35
Langley Avatar answered Oct 20 '22 05:10

Langley