2016-04-04 5 views
1

Nachdem ich einige Themen angeschaut habe, die diesen Fehler diskutieren, kann ich keinen Grund finden, dass mein Code EXCEPTION: Attempt to use a dehydrated detector: PortsInputComponent_1 -> valueChange produziert. Ich denke nicht, dass der Stacktrace nützlich ist, da es nur ein Winkelcode ist und nicht meins.Angular exception: Versuch, einen dehydrierten Detektor zu verwenden

ich an diesen Stellen haben gesucht: Angular2 EXCEPTION: Attempt to detect changes on a dehydrated detector, EXCEPTION: Attempt to detect changes on a dehydrated detector, What is a dehydrated detector and how am I using one here? und bei dieser Github Ausgabe https://github.com/angular/angular/issues/6786.

Sie alle scheinen einige asynchrone Operationen zu verwenden, was ich nicht bin, und keine dieser Lösungen passt zu meinem Projekt. Bitte schließen Sie es nicht als Duplikat.

Im Grunde versuche ich einen speziellen Eingang für mehrere Ports. Ich möchte immer eine leere Eingabe haben, so dass der Benutzer keine Taste drücken muss, um eine neue hinzuzufügen. Ich möchte jedoch nicht mehr als eine leere Eingabe haben, also muss ich sie entfernen, wenn der Benutzer das letzte Zeichen löscht. Die Demo unten macht das perfekt.

Hier ist der Code innerhalb des Plunker:

import { Component, Input }    from 'angular2/core'; 

@Component({ 
    selector: 'my-ports-input', 
    template:` 
<div layout-gt-sm="row" layout-wrap> 

    <md-input-container class="md-block" flex-gt-sm 
     *ngFor="#port of values() ; #i = index ;"> 
    <label>Port</label> 
    <input md-input class="ports-input" type="text" size="6" 
     [value]="port.title" (input)="changeValueAtIndex(i, $event)" /> 
    </md-input-container> 
</div> 
` 
}) 

export class PortsInputComponent { 
    // More complex model that contains an array of string values 
    @Input() attribute: {value : string[]} 
    strings = [] 

    changeValueAtIndex(index, event) { 
    // Case where we changed the value of the latest port : we add a new input 
    if (!this.attribute.value[index]) { 
     this.strings.push({ title: '' }) 
    } 

    this.attribute.value[index] = event.target.value 

    if (event.target.value.length === 0) { 
     this.attribute.value.splice(index, 1) 
     this.strings = [] // Should reload the array, but also causes the issue below 
    } 
    } 

    // Use this function that returns an array of objects instead of an array of string. 
    // Using directly attribute.value (array of string) cause this error: 
    // https://github.com/angular/angular/issues/6786 
    // 
    // Returning directly this.attribute.value.map((value) => { return {title: value} }) 
    // causes an infinite loop of error... for some reason 
    // So use an intermediate variable instead 
    values() { 
    if (!this.strings.length) { 
     let values: string[] = this.attribute.value 
     this.strings = values.map((value) => { return {title: value} }) 
     this.strings.push({ title: '' }) 
    } 
    return this.strings 
    // return this.attribute.value.map((value) => { return {title: value} }) 
    } 
} 

Hat jemand versteht, warum dieser Fehler in meinem Fall geworfen wird?

Ich wollte diesen Fehler in a plunker reproduzieren, aber leider verursacht es keine Ausnahme, der einzige Unterschied, den ich zwischen meiner App und dem Plunker sehe, ist die Variable. In meiner App ist es ein Modell und kein JSON-Objekt, könnte es etwas verändern?

+0

Das Plunker Beispiel wird mit 'beta.8' daher sollte es reproduzierbar sein. AFAIR bezieht sich auf Komponenten, die nach oder während des Entfernens ein Ereignis auslösen. –

+0

In der Tat schaute ich auf die README.md-Datei, die Beta 0 angibt, selbst wenn es Beta 8 im Index lädt. Das ist auch, was ich aus dem GitHub-Thema verstanden habe, kann aber nicht herausfinden, warum es in meinem Fall passiert. – Sunder

+0

Die Readme ist gerade veraltet. –

Antwort

1

Delaying diesen Code ein bisschen könnte (nicht getestet, weil ich nicht reproduzieren kann) arbeiten um der Lage sein,

changeValueAtIndex(index, event) { 
    setTimeout(() => { 
     // Case where we changed the value of the latest port : we add a new input 
     if (!this.attribute.value[index]) { 
     this.strings.push({ title: '' }) 
     } 

     this.attribute.value[index] = event.target.value 

     if (event.target.value.length === 0) { 
     this.attribute.value.splice(index, 1) 
     this.strings = [] // Should reload the array, but also causes the issue below 
     } 
    },0}); 
    } 
+0

Ein setTimeOut von 1ms (0 hat nicht funktioniert) um die Zeile' this.strings = [] 'entfernte den Fehler, Danke. Aber könnten Sie erklären, warum das Verzögern dieses Codes um 1 ms verhindert, dass ein Ereignis von einer entfernten Komponente ausgelöst wird? – Sunder

+1

Es gibt einige Dinge, die sich ändern, während Angular die vorherige Änderung noch verarbeitet. 'setTimeout' ändert nur die Reihenfolge, in der Dinge verarbeitet werden. Angular kann seine Sachen vervollständigen und dieser Code wird erst danach ausgeführt, wenn Angular wieder in einem stabilen Zustand ist. Wenn das Problem in Angular behoben wird, sollte intern darauf geachtet werden, dass Dinge nicht in der erwarteten Reihenfolge ausgeführt werden. –

Verwandte Themen