What is the RendererAdapter?

时光总嘲笑我的痴心妄想 提交于 2019-12-11 06:27:17

问题


While I couldn't reproduce the issue, please take a look my plunker.

I received following error when I try to open the dialog in my local workspace:

ERROR TypeError: this._renderer.setProperty is not a function
at NgbRadio.set [as value] (radio.js:133)
at updateProp (core.es5.js:11160)
at checkAndUpdateDirectiveInline (core.es5.js:10852)
at checkAndUpdateNodeInline (core.es5.js:12382)
at checkAndUpdateNode (core.es5.js:12321)
at debugCheckAndUpdateNode (core.es5.js:13180)
at debugCheckDirectivesFn (core.es5.js:13121)
at Object.eval [as updateDirectives] (AdEditorComponent.html:48)
at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:13106)
at checkAndUpdateView (core.es5.js:12288)

I tested many smaller cases then found the RendererAdapter encloses valid DebugRenderer2 instance in NgbRadio component.

So, I wrote a hack into the NgbRadio and NgbActiveLabel's constructor to test, then the application works fine:

this._renderer = _renderer.constructor.name === 'RendererAdapter'? _renderer.delegate: _renderer;

And this structure in the template makes the error:

<div [ngSwitch]="conditionalProperty">
  <my-component *ngSwitchCase="'case1'" ...></my-component>
  <my-another-comp *ngSwitchCase="'case2'" ...></my-another-comp>
</div>

Let me list two cases the dialog could open in my local:

  • Do not inject any pipe dependency (they don't care the pipes are my custom or provided from @angular/common) into the components has ngSwitchCase attribute at the template
  • Only one component in the ngSwitch div (but could contains other normal divs have ngSwitchCase)

I tested the latest version of Chrome, Safari, and Firefox and my angular version is 4.2.4.

I couldn't find any useful article about RendererAdapter from Google. I might use above hack to solve this but don't want to ignore what was the real problem. I would appreciate any answers.


回答1:


The default renderer now is Renderer2. So when you inject a renderer into a component you should use Renderer2 token:

class MyComponent {
   constructor(renderer: Renderer2)

However, earlier versions of Angular used Renderer which is now deprecated and to inject it Renderer token was used:

class MyComponent {
   constructor(renderer: Renderer)

RendererAdapter is a class that maps old API to new API, for example, the first renderer had listenGlobal method, while the latter API uses listen. And here is the mapping for this specific method:

  listenGlobal(target: string, name: string, callback: Function): Function {
      return this.delegate.listen(target, name, <any>callback);
  }

where delegate is an instance of Renderer2.

If you don't use Renderer injection token the RendererAdapter will not be created. It's possible that the version of ngbRadio uses old renderer. The current version seem to be using new renderer.

See also

  • https://github.com/angular/angular/issues/17558
  • https://github.com/angular/angular/issues/17378


来源:https://stackoverflow.com/questions/44792622/what-is-the-rendereradapter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!