Website-Suche

javascript - angular: Aufruf von el.setAttribute führt zu einem Fehler


Ich versuche, ein neues Attribut (definiert als 'data-num') innerhalb jedes Elements (bezeichnet als el) in Bezug auf [ngDN] (als Instanz der Direktive NgDNDirective) zu setzen.

Konzept :

Der unten stehende Code erklärt, wie NgDNDirective funktionieren soll:

  1. TS-Teil:

    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-Teil:

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

Problem :

Nach dem Ausführen des Tests zeigt mir die Konsole die folgenden Informationen:

  

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

Das bedeutet, dass die eingespritzte Instanz von Renderer2 von NgLoopDirective zu NgDNDirective ohne die Methode setAttribute kommt. Warum tritt dies auf?

Weitere Informationen:

  

ng -v _ _ ____ _ _ / \ _ __ __ _ _ _| | __ _ _ __ / | | | | / △ \ | ' \ / _| | | | |/ _ | '| | | | | | | / \| | | | (| | || | | (| | | | || | | | // __| ||__, |__,||__,|| ____|_____|| |/ @angular/cli: 1.2.3 node: 6.11.0 os: linux x64 @angular/animations: 4.3.3 @angular/common: 4.3.3 @angular/compiler: 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/compiler-cli: 4.3.3 @angular/language-service: 4.3.3

Antwort #1

Renderer2#setAttribute(el, name, value) ruft am Ende el.setAttribute(name, value) auf. Der Fehler besagt, dass das als el übergebene Argument keine setAttribute()-Methode hat. Und das liegt daran, dass es sich um eine ElementRef-Instanz handelt.

Sie sollten das tatsächliche DOM-Element übergeben:

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