Solvedangular Error: No Provider for Renderer 2!

I'm submitting a ...

[ ] Regression (behavior that used to work and stopped working in a new release)
[x] Bug report 
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

I am doing what I believe to be recommended service injection, with Renderer2 onto the component. I get no errors in my compiler but this error in my console on click of a button in the said component.(See stackoverflow post)

Expected behavior

Refactor my service so it works with migration.

Minimal reproduction of the problem with instructions

https://stackoverflow.com/questions/44812394/error-no-provider-for-renderer2-angular-v-4-1-3

What is the motivation / use case for changing the behavior?

Similar recommended practice with original Renderer could be injected like shown.

Please tell us about your environment

Angular version: X.Y.Z

4.1.3, Still seems to be a problem on latest version.
Browser:
- [x] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
 
For Tooling issues:
- Node version: XX 
- Platform: 
Node: 7.10.0
Mac OS Sierra 10.12.1

Others:
23 Answers

✔️Accepted Answer

@ericcarraway I don't know is it a right way to access renderer from service or not... but reading ts https://github.com/angular/angular/blob/5.1.1/packages/core/src/render/api.ts#L142-L190 (version 4.x as well) I've learned to use RendererFactory2 to get Renderer2 instance inside the Service.

@Injectable()
class MyService {
  private renderer: Renderer2;
  
  constructor(rendererFactory: RendererFactory2) {
    this.renderer = rendererFactory.createRenderer(null, null);
  }
}

http://plnkr.co/edit/mnyqG6fkhUR0WIX3c45U?p=preview
UPDATED: As @willyboy mentioned createRenderer needs two arguments.
Following the link you can find in both sources it can be createRenderer(null, null)

Other Answers:

As I can see Renderer2 don't work in services and work in components (in Angular 4.4.5)

@willyboy rendererFactory.createRenderer(null, null) would help, if no (concrete) parameters passed, it will just return the default renderer without create a new one.

That's what guarded by current implementation:

createRenderer(element: any, type: RendererType2|null): Renderer2 {
  if (!element || !type) {
    return this.defaultRenderer;
  }
  //...   
}

@trotyl thanks for a great tip! Created a token for it so it could be reused easily:

export const DEFAULT_RENDERER = new InjectionToken<Renderer2>(
    'A Renderer2 for global services',
    {
        factory: () => inject(RendererFactory2).createRenderer(null, null),
    },
);

More Issues: