错误:Renderer2 没有提供程序!角度 v 4.1.3

his*_*ag3 1 dom webpack angular

我目前正在重构我的一项在升级时中断的服务。我不得不更换 browserdomadapter(); 以及其他一些已弃用的方法。

由于来自 2.1ish 的各种弃用和各种重大更改,我不得不改变我们向组件提供此特定服务的方式。我现在将它直接注入到组件上,我在各种答案(由 angular devs 提供)中看到这是推荐的做法。

这是错误:

在此处输入图片说明

问题是我已经在提供者的组件中引用了注入的服务,如下面的相关代码所示:

import {Location} from "@angular/common";
import {Component, Injectable, Renderer2, Inject} from "@angular/core";
import {SerieService} from "../shared/services/serie.service";
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { CategoryService } from "../shared/services/category.service";
import {Router, ActivatedRoute, RouterModule, NavigationEnd} from "@angular/router";

import {Http, HttpModule} from "@angular/http";
import {PageviewService} from "../shared/services/pageview.service";
import {Title, DOCUMENT} from '@angular/platform-browser';
import {SeoService} from '../shared/services/seo.service';

@Injectable()
export class Service {


private metaDescription: HTMLElement;

private headElement: HTMLElement;

private robots: HTMLElement;



constructor(@Inject(DOCUMENT) private document: any, private r: Renderer2, private titleService: Title){
this.headElement = this.document.head;
this.metaDescription = this.getOrCreateMetaElement('description');

}

 public setMetaDescription(description: string) {
  this.r.setAttribute(this.metaDescription, 'content', description)
 }

 public setMetaRobots(robots: string) {
  this.r.setAttribute(this.robots, 'content', robots);
 }

 public setTitle(newTitle: string) {
  this.titleService.setTitle(newTitle + ' | Stareable');
 }

 private getOrCreateMetaElement(name: string): HTMLElement {
     let el: HTMLElement;
     el = this.document.querySelector('meta[name=' + name + ']');
     if (el === null) {
         el = this.document.setAttribute('meta');
         this.headElement.appendChild(el);
     }
     return el;
   }

 }




 @Component({
   inputs: ['category'],
   templateUrl: './categories.component.html',
   styleUrls: ['./categories.component.scss'],
   providers: [ Service ]
 })

export class CategoriesComponent {

  public category: string;
  public seriesList: any;
  public message: string;
  public loading: boolean;
  public errorMessage: string;

  private slug:string;

 constructor (
   private service: Service,
   private _router: Router,
   private _activatedRoute: ActivatedRoute,
   private _categoryService: CategoryService,
   private _seriesService: SerieService,
   private _pageviewService: PageviewService,
   private location: Location,
   private _httpService: Http,
   private seoService: SeoService
  ) {
   this._router.events.subscribe((event) => {
    if (event instanceof NavigationEnd){
        //TODO: FIX TO RECOGNIZE PREVIOUS ROUTE -- THIS WILL CAUSE DUPLICATE REQUESTING URL
        let slug = this._activatedRoute.snapshot.params['slug'];
        this.slug = slug;
        this.category = this._activatedRoute.snapshot.params['slug'];
        this.getSeriesList(slug, null);
     }
  })
}

ngOnInit(){
  let slug = this._activatedRoute.snapshot.params['slug'];
  this.loading = true;
  this.category = this._activatedRoute.snapshot.params['slug'];
  this.getSeriesList(slug,"title");
  this.service.setTitle(slug);
  this.service.setMetaDescription(slug);
  this.service.setMetaRobots('Index, Follow');


 this._pageviewService.addPageview(
 this.location.path(),"CATEGORY",slug,null)
    .subscribe(res => {},err => {});
}

getSeriesList(slug, order_by) {
    this._categoryService.getSeriesByCategory(slug, order_by)
    .subscribe(
        seriesList => this.seriesList = seriesList,
        error =>  this.errorMessage = <any>error);
}

 onReShuffle(order_by:string){
     this.loading = true;





  this._categoryService.getSeriesByCategory(
  this._activatedRoute.snapshot.params['slug'], order_by)
    .subscribe(
        seriesList => {
            this.seriesList = seriesList;
            this.loading = false;
        },
        error =>  this.errorMessage = <any>error);

 }

 openPlaylistModal(series) {
   // todo: open modal and pass series
   console.log(series);
   return
 }

 loadMore() {
   this._httpService.get(this.seriesList.next_url)
    .subscribe((res) => {
        var results = res.json();
        this.seriesList.result = t 
        this.seriesList.result.concat(results.result);
        if(results.next_url){
            this.seriesList.next_url = results.next_url;
        }
        else {
            this.seriesList.next_url = false;
        }
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

不知道我做错了什么。有没有其他方法可以做到这一点,我不知道?

Eug*_*lov 5

您不能注入Renderer2,但我们可以运行RendererFactory2以获取服务Renderer2内的实例@Injectable()。例如,Angular 在 webworkers 内部使用的方式。

我已经用下面的代码解决了这个问题:

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

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

    constructor(rendererFactory: RendererFactory2) {
        this.renderer = rendererFactory.createRenderer(null, null);
    }
}
Run Code Online (Sandbox Code Playgroud)

RendererFactory2.createRenderer方法参数为:

  • hostElement 带类型 any
  • type 带类型 RendererType2|null

你可以看到(null, null)参数在这里:https : //github.com/angular/angular/blob/e3140ae888ac4037a5f119efaec7b1eaf8726286/packages/core/src/render/api.ts#L129

PS 将 Renderer2 注入服务并不是最好的主意。任何渲染器操作都应该在组件和指令中进行。