错误:Renderer2没有提供者! Angular v 4.1.3

时间:2017-06-28 20:54:57

标签: angular dom webpack

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

由于来自2.1ish的各种弃用以及各种重大变化,我不得不改变将此特定服务提供给组件的方式。我现在直接将它注入到组件中,我在各种答案中看到(通过角度开发)是推荐的做法。

这是错误:

enter image description here

问题是我已经在提供商的组件中引用了注入的服务,您可以在下面的相关代码中看到:

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

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

1 个答案:

答案 0 :(得分:2)

您无法注入Renderer2,但我们可以运行RendererFactory2来获取Renderer2服务中的@Injectable()实例。 例如,Angular在网络工作者中有内部使用的方式。

我已用以下代码解决了问题:

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

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

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

RendererFactory2.createRenderer方法的参数是:

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

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

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