最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - angular: Calling el.setAttribute results in an error - Stack Overflow

programmeradmin3浏览0评论

I'm trying to set a new attribute (defined as 'data-num') within each element (labeled as el) referring to [ngDN] (as an instance of the directive NgDNDirective).

Concept:

The code below explains how NgDNDirective is intended to work:

  1. TS part:

    import { Directive, Input, ElementRef, Renderer2, EventEmitter } from '@angular/core';
    
    @Directive({
      selector: '[ngDN]'
    })
    export class NgDNDirective {
    
      private dn: number = -1
    
      @Input() set ngDN(dn: number) {
        this.dn = dn
      }
    
      @Input() set EV(ref: {ev: EventEmitter<void>}) {
        ref.ev.subscribe(() => {
          console.log('data-num:', this.dn)
          this.renderer.setAttribute(this.elRef, 'data-num', this.dn.toString())
        })
      }
    
      constructor(private elRef: ElementRef,
                  private renderer: Renderer2) {}
    
    }
    
    @Directive({
      selector: '[ngLoop]'
    })
    export class NgLoopDirective {
    
      @Input() set ngLoop(iter_count: number) {
        this.container.clear()
        for (let i=0; i<iter_count; i++) {
          let ee: EventEmitter<void> = new EventEmitter<void>()
          let ref = {ev: ev}
          let ev = this.container.createEmbeddedView(this.template, {index: i, ev: ref})
          ev.detectChanges()
          ee.emit()
        }
      }
    
      constructor(private template: TemplateRef<any>,
                  private container: ViewContainerRef) {}
    
    }
    
  2. HTML part:

    <ng-template [ngLoop]="10" let-i="index" let-ref="ev">
      <a href="#" [ngDN]="i" [EV]="ref"></a>
    </ng-template>
    

Problem:

After running the test, the console shows me the following information:

data-num: 0

ERROR TypeError: el.setAttribute is not a function Stack trace: ../../../platform-browser/@angular/platform-browser.es5.js/DefaultDomRenderer2.prototype.setAttribute@http://localhost:8888/vendor.bundle.js:78803:13 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:66266:9 set/<@http://localhost:8888/main.bundle.js:869:17 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:56260:36 ../../../../rxjs/Subscriber.js/SafeSubscriber.prototype.__tryOrUnsub@http://localhost:8888/vendor.bundle.js:1558:13 ../../../../rxjs/Subscriber.js/SafeSubscriber.prototype.next@http://localhost:8888/vendor.bundle.js:1505:17 ../../../../rxjs/Subscriber.js/Subscriber.prototype._next@http://localhost:8888/vendor.bundle.js:1445:9 ../../../../rxjs/Subscriber.js/Subscriber.prototype.next@http://localhost:8888/vendor.bundle.js:1409:13 ../../../../rxjs/Subject.js/Subject.prototype.next@http://localhost:8888/vendor.bundle.js:1153:17 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:56234:54 set@http://localhost:8888/main.bundle.js:928:17 updateProp@http://localhost:8888/vendor.bundle.js:63715:5 checkAndUpdateDirectiveInline@http://localhost:8888/vendor.bundle.js:63407:19 checkAndUpdateNodeInline@http://localhost:8888/vendor.bundle.js:64945:17 checkAndUpdateNode@http://localhost:8888/vendor.bundle.js:64884:16 debugCheckAndUpdateNode@http://localhost:8888/vendor.bundle.js:65745:38 debugCheckDirectivesFn@http://localhost:8888/vendor.bundle.js:65686:13 View_HomeComponent_4/<@ng:///AppModule/HomeComponent.ngfactory.js:121:9 debugUpdateDirectives@http://localhost:8888/vendor.bundle.js:65671:12 checkAndUpdateView@http://localhost:8888/vendor.bundle.js:64851:5 callViewAction@http://localhost:8888/vendor.bundle.js:65216:21 execEmbeddedViewsAction@http://localhost:8888/vendor.bundle.js:65174:17 checkAndUpdateView@http://localhost:8888/vendor.bundle.js:64852:5 callViewAction@http://localhost:8888/vendor.bundle.js:65216:21 execComponentViewsAction@http://localhost:8888/vendor.bundle.js:65148:13 checkAndUpdateView@http://localhost:8888/vendor.bundle.js:64857:5 callViewAction@http://localhost:8888/vendor.bundle.js:65216:21 execEmbeddedViewsAction@http://localhost:8888/vendor.bundle.js:65174:17 checkAndUpdateView@http://localhost:8888/vendor.bundle.js:64852:5 callViewAction@http://localhost:8888/vendor.bundle.js:65216:21 execComponentViewsAction@http://localhost:8888/vendor.bundle.js:65148:13 checkAndUpdateView@http://localhost:8888/vendor.bundle.js:64857:5 callWithDebugContext@http://localhost:8888/vendor.bundle.js:66071:39 debugCheckAndUpdateView@http://localhost:8888/vendor.bundle.js:65611:12 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:62782:9 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:57420:58 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:57420:13 next/<@http://localhost:8888/vendor.bundle.js:57297:100 ../../../../zone.js/dist/zone.js/http://localhost:8888/polyfills.bundle.js:2936:17 onInvoke@http://localhost:8888/vendor.bundle.js:56503:24 ../../../../zone.js/dist/zone.js/http://localhost:8888/polyfills.bundle.js:2935:17 ../../../../zone.js/dist/zone.js/http://localhost:8888/polyfills.bundle.js:2686:24 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:56434:54 next@http://localhost:8888/vendor.bundle.js:57297:70 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:56248:36 ../../../../rxjs/Subscriber.js/SafeSubscriber.prototype.__tryOrUnsub@http://localhost:8888/vendor.bundle.js:1558:13 ../../../../rxjs/Subscriber.js/SafeSubscriber.prototype.next@http://localhost:8888/vendor.bundle.js:1505:17 ../../../../rxjs/Subscriber.js/Subscriber.prototype._next@http://localhost:8888/vendor.bundle.js:1445:9 ../../../../rxjs/Subscriber.js/Subscriber.prototype.next@http://localhost:8888/vendor.bundle.js:1409:13 ../../../../rxjs/Subject.js/Subject.prototype.next@http://localhost:8888/vendor.bundle.js:1153:17 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:56234:54 checkStable@http://localhost:8888/vendor.bundle.js:56468:13 onLeave@http://localhost:8888/vendor.bundle.js:56547:5 onInvokeTask@http://localhost:8888/vendor.bundle.js:56497:17 ../../../../zone.js/dist/zone.js/http://localhost:8888/polyfills.bundle.js:2968:17 ../../../../zone.js/dist/zone.js/http://localhost:8888/polyfills.bundle.js:2736:28 ../../../../zone.js/dist/zone.js/http://localhost:8888/polyfills.bundle.js:3043:24 invokeTask@http://localhost:8888/polyfills.bundle.js:3915:9 globalZoneAwareCallback@http://localhost:8888/polyfills.bundle.js:3933:17

This means that the injected instance of Renderer2 from NgLoopDirective to NgDNDirective, es without setAttribute method. Why does this occur?

Further informations:

ng -v _ _ ____ _ _ / \ _ __ __ _ _ _| | __ _ _ __ / | | | | / △ \ | ' \ / _| | | | |/ _ | '| | | | | | | / \| | | | (| | || | | (| | | | || | | | // __| ||__, |__,||__,||
____|_____|| |/ @angular/cli: 1.2.3 node: 6.11.0 os: linux x64 @angular/animations: 4.3.3 @angular/mon: 4.3.3 @angular/piler: 4.3.3 @angular/core: 4.3.3 @angular/forms: 4.3.3 @angular/http: 4.3.3 @angular/platform-browser: 4.3.3 @angular/platform-browser-dynamic: 4.3.3 @angular/router: 4.3.3 @angular/cli: 1.2.3 @angular/piler-cli: 4.3.3 @angular/language-service: 4.3.3

I'm trying to set a new attribute (defined as 'data-num') within each element (labeled as el) referring to [ngDN] (as an instance of the directive NgDNDirective).

Concept:

The code below explains how NgDNDirective is intended to work:

  1. TS part:

    import { Directive, Input, ElementRef, Renderer2, EventEmitter } from '@angular/core';
    
    @Directive({
      selector: '[ngDN]'
    })
    export class NgDNDirective {
    
      private dn: number = -1
    
      @Input() set ngDN(dn: number) {
        this.dn = dn
      }
    
      @Input() set EV(ref: {ev: EventEmitter<void>}) {
        ref.ev.subscribe(() => {
          console.log('data-num:', this.dn)
          this.renderer.setAttribute(this.elRef, 'data-num', this.dn.toString())
        })
      }
    
      constructor(private elRef: ElementRef,
                  private renderer: Renderer2) {}
    
    }
    
    @Directive({
      selector: '[ngLoop]'
    })
    export class NgLoopDirective {
    
      @Input() set ngLoop(iter_count: number) {
        this.container.clear()
        for (let i=0; i<iter_count; i++) {
          let ee: EventEmitter<void> = new EventEmitter<void>()
          let ref = {ev: ev}
          let ev = this.container.createEmbeddedView(this.template, {index: i, ev: ref})
          ev.detectChanges()
          ee.emit()
        }
      }
    
      constructor(private template: TemplateRef<any>,
                  private container: ViewContainerRef) {}
    
    }
    
  2. HTML part:

    <ng-template [ngLoop]="10" let-i="index" let-ref="ev">
      <a href="#" [ngDN]="i" [EV]="ref"></a>
    </ng-template>
    

Problem:

After running the test, the console shows me the following information:

data-num: 0

ERROR TypeError: el.setAttribute is not a function Stack trace: ../../../platform-browser/@angular/platform-browser.es5.js/DefaultDomRenderer2.prototype.setAttribute@http://localhost:8888/vendor.bundle.js:78803:13 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:66266:9 set/<@http://localhost:8888/main.bundle.js:869:17 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:56260:36 ../../../../rxjs/Subscriber.js/SafeSubscriber.prototype.__tryOrUnsub@http://localhost:8888/vendor.bundle.js:1558:13 ../../../../rxjs/Subscriber.js/SafeSubscriber.prototype.next@http://localhost:8888/vendor.bundle.js:1505:17 ../../../../rxjs/Subscriber.js/Subscriber.prototype._next@http://localhost:8888/vendor.bundle.js:1445:9 ../../../../rxjs/Subscriber.js/Subscriber.prototype.next@http://localhost:8888/vendor.bundle.js:1409:13 ../../../../rxjs/Subject.js/Subject.prototype.next@http://localhost:8888/vendor.bundle.js:1153:17 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:56234:54 set@http://localhost:8888/main.bundle.js:928:17 updateProp@http://localhost:8888/vendor.bundle.js:63715:5 checkAndUpdateDirectiveInline@http://localhost:8888/vendor.bundle.js:63407:19 checkAndUpdateNodeInline@http://localhost:8888/vendor.bundle.js:64945:17 checkAndUpdateNode@http://localhost:8888/vendor.bundle.js:64884:16 debugCheckAndUpdateNode@http://localhost:8888/vendor.bundle.js:65745:38 debugCheckDirectivesFn@http://localhost:8888/vendor.bundle.js:65686:13 View_HomeComponent_4/<@ng:///AppModule/HomeComponent.ngfactory.js:121:9 debugUpdateDirectives@http://localhost:8888/vendor.bundle.js:65671:12 checkAndUpdateView@http://localhost:8888/vendor.bundle.js:64851:5 callViewAction@http://localhost:8888/vendor.bundle.js:65216:21 execEmbeddedViewsAction@http://localhost:8888/vendor.bundle.js:65174:17 checkAndUpdateView@http://localhost:8888/vendor.bundle.js:64852:5 callViewAction@http://localhost:8888/vendor.bundle.js:65216:21 execComponentViewsAction@http://localhost:8888/vendor.bundle.js:65148:13 checkAndUpdateView@http://localhost:8888/vendor.bundle.js:64857:5 callViewAction@http://localhost:8888/vendor.bundle.js:65216:21 execEmbeddedViewsAction@http://localhost:8888/vendor.bundle.js:65174:17 checkAndUpdateView@http://localhost:8888/vendor.bundle.js:64852:5 callViewAction@http://localhost:8888/vendor.bundle.js:65216:21 execComponentViewsAction@http://localhost:8888/vendor.bundle.js:65148:13 checkAndUpdateView@http://localhost:8888/vendor.bundle.js:64857:5 callWithDebugContext@http://localhost:8888/vendor.bundle.js:66071:39 debugCheckAndUpdateView@http://localhost:8888/vendor.bundle.js:65611:12 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:62782:9 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:57420:58 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:57420:13 next/<@http://localhost:8888/vendor.bundle.js:57297:100 ../../../../zone.js/dist/zone.js/http://localhost:8888/polyfills.bundle.js:2936:17 onInvoke@http://localhost:8888/vendor.bundle.js:56503:24 ../../../../zone.js/dist/zone.js/http://localhost:8888/polyfills.bundle.js:2935:17 ../../../../zone.js/dist/zone.js/http://localhost:8888/polyfills.bundle.js:2686:24 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:56434:54 next@http://localhost:8888/vendor.bundle.js:57297:70 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:56248:36 ../../../../rxjs/Subscriber.js/SafeSubscriber.prototype.__tryOrUnsub@http://localhost:8888/vendor.bundle.js:1558:13 ../../../../rxjs/Subscriber.js/SafeSubscriber.prototype.next@http://localhost:8888/vendor.bundle.js:1505:17 ../../../../rxjs/Subscriber.js/Subscriber.prototype._next@http://localhost:8888/vendor.bundle.js:1445:9 ../../../../rxjs/Subscriber.js/Subscriber.prototype.next@http://localhost:8888/vendor.bundle.js:1409:13 ../../../../rxjs/Subject.js/Subject.prototype.next@http://localhost:8888/vendor.bundle.js:1153:17 ../../../core/@angular/core.es5.js/http://localhost:8888/vendor.bundle.js:56234:54 checkStable@http://localhost:8888/vendor.bundle.js:56468:13 onLeave@http://localhost:8888/vendor.bundle.js:56547:5 onInvokeTask@http://localhost:8888/vendor.bundle.js:56497:17 ../../../../zone.js/dist/zone.js/http://localhost:8888/polyfills.bundle.js:2968:17 ../../../../zone.js/dist/zone.js/http://localhost:8888/polyfills.bundle.js:2736:28 ../../../../zone.js/dist/zone.js/http://localhost:8888/polyfills.bundle.js:3043:24 invokeTask@http://localhost:8888/polyfills.bundle.js:3915:9 globalZoneAwareCallback@http://localhost:8888/polyfills.bundle.js:3933:17

This means that the injected instance of Renderer2 from NgLoopDirective to NgDNDirective, es without setAttribute method. Why does this occur?

Further informations:

ng -v _ _ ____ _ _ / \ _ __ __ _ _ _| | __ _ _ __ / | | | | / △ \ | ' \ / _| | | | |/ _ | '| | | | | | | / \| | | | (| | || | | (| | | | || | | | // __| ||__, |__,||__,||
____|_____|| |/ @angular/cli: 1.2.3 node: 6.11.0 os: linux x64 @angular/animations: 4.3.3 @angular/mon: 4.3.3 @angular/piler: 4.3.3 @angular/core: 4.3.3 @angular/forms: 4.3.3 @angular/http: 4.3.3 @angular/platform-browser: 4.3.3 @angular/platform-browser-dynamic: 4.3.3 @angular/router: 4.3.3 @angular/cli: 1.2.3 @angular/piler-cli: 4.3.3 @angular/language-service: 4.3.3

Share Improve this question asked Sep 16, 2017 at 22:38 user6039980user6039980 3,5068 gold badges35 silver badges58 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 15

Renderer2#setAttribute(el, name, value) ends up calling el.setAttribute(name, value). What the error says is that the argument passed as el does not have a setAttribute() method. And that is because it is an ElementRef instance.

You should be passing the actual DOM element:

this.renderer.setAttribute(this.elRef.nativeElement, ...)

You are using the 'ngDN' attribute as the selector for your directive, but you are also trying to set the value of that attribute to the value of your loop index.

Using the attribute as the selector should be fine, but you shouldn't be trying to set it's value. Your Directive has an input named 'ngDN':

  private dn: number = -1

  @Input() set ngDN(dn: number) {
    this.dn = dn
  }

You should probably change this to:

@Input() dn: number = -1;

and then change your template to:

<ng-template [ngLoop]="10" let-i="index" let-ref="ev">
  <a href="#" ngDN [dn]="i" [EV]="ref"></a>
</ng-template>
发布评论

评论列表(0)

  1. 暂无评论