Angular 4 ControlValueAccessor-Wert beim Senden und Wert ändert Ereignisse

8

In meinem Angular (4 + Typescript) Projekt habe ich bereits eine vorbereitete Komponente verwendet (es ist nicht wirklich wichtig, was die Erweiterung von ControlValueAccessor ist, aber wenn das wichtig ist, habe ich ng2-select verwendet), was ich besser wollte UX und schöneres Aussehen. Nach dem Einbinden in meine Formular-Komponente, die reaktive Formulare verwendet, habe ich gesehen, dass ich beim Submit ein Objekt (basierend auf der Klasse SelectItem, das in der vorbereiteten Komponente verwendet wird) zurückgewinnen kann, um ausgewählte Objekte zu verwalten - so:

%Vor%

Da die Komponente im Grunde genommen nur ein Ersatz für die standardmäßige Auswahlsteuerung ist, erwartete ich, dass ich eine ID des ausgewählten Elements, das als String gebildet wurde, zurückbekommen werde - wie folgt:

%Vor%

Nachdem ich erfahren habe, was ControlValueAccessor tatsächlich ist und wie es funktioniert, habe ich die Art und Weise geändert, wie es beim Senden (oder besser beim Ändern des Elements - onChange ) an die ID eines Elements zurückgegeben wird. Das Problem wurde für einige Zeit gelöst, bis ich anfing, vordefinierte Werte (auf Editierinstanz) zu setzen, um Kontrollen anstelle von leeren Werten zu bilden (beim Hinzufügen der Instanz). Ich habe herausgefunden, dass dieses Mal die writeValue der Formularsteuerung Werte zuweist, die auf dem basieren, was sie als vordefinierten Wert gesendet hat. Also für den Fall, dass ich einen vordefinierten Wert als ... gesendet habe.

%Vor%

... das war auch der Wert in Objekt beim Senden, genau wie im ersten Codebeispiel oben. Ich habe einen Workaround dafür gemacht, um den richtigen Wert für die Steuerung mit onChange direkt nach dem Aufruf von writeValue zu vergeben. Das war ein wirklich unpassender Weg, aber ich konnte nichts anderes herausfinden:

%Vor%

Und das hat auch soweit geklappt, dass ich nicht mit der Anmeldung bei valueChanges der Formularsteuerung begonnen habe. Das Problem ist, dass bei jeder Zuweisung eines vordefinierten Werts zur vorbereiteten Komponente auch der Wert, der nach dem Senden verwendet wird, an die Abonnenten zurückgesendet wird, auch wenn { emitEvent: false } verwendet wird.

Das sind also die Dinge, die ich mit vorbereiteten Komponenten irgendwie behandelt haben möchte, da ich den richtigen Wert aus der Kontrolle beim Senden bekommen möchte und ich keine Änderung an Abonnenten ausgeben lassen soll, bis der Wert wirklich nicht geändert, nicht nur ersetzt wird als vordefinierter Wert. Irgendeine Idee, wie man damit umgeht, wird geschätzt.

    
user1257255 20.04.2017, 09:07
quelle

2 Antworten

2
___ tag123javascript ___ JavaScript (nicht zu verwechseln mit Java) ist eine dynamische Sprache mit mehreren Paradigmen auf hoher Ebene, die sowohl für das clientseitige als auch für das serverseitige Scripting verwendet wird. Verwenden Sie dieses Tag für Fragen zu ECMAScript und seinen verschiedenen Dialekten / Implementierungen (außer ActionScript und Google-Apps-Script). ___ tag123forms ___ Ein Formular ist im Wesentlichen ein Container, der verwendet werden kann, um eine beliebige Menge einer Teilmenge verschiedener Datentypen zu speichern. HTML-Formulare werden verwendet, um Daten an einen Server zu übergeben. VB- und C # -Formulare sind die Fenster, die für die Interaktion mit dem Benutzer verwendet werden. ___ tag123angular ___ Fragen zu Angular, dem Web-Framework von Google. Verwenden Sie dieses Tag für Angular-Fragen, die nicht für eine einzelne Version spezifisch sind. Verwenden Sie für das ältere AngularJS-Webframework (1.x) das angularjs-Tag. ___ tag123controls ___ Verwenden Sie dieses Tag zum Programmieren von Szenarien in Bezug auf Steuerelemente (interaktive Elemente der Benutzeroberfläche). ___ answer44015758 ___

Grundsätzlich stellte sich die Frage, ob es möglich ist, verschiedene Werttypen als Anfangswert an eine Steuerkomponente zu senden, die mit der Methode writeValue behandelt werden. Dieser sollte dann den Wert in eine String-ID oder ein Array von String-IDs umwandeln, je nachdem, welcher Typ ausgewählt ist - Einzelwert oder mehrere Werte. Wie Frank in seiner Antwort sagte, ist es etwas peinlich, dies zu tun und onChange mit setTimeout Workaround aufzurufen.

Die Lösung besteht also darin, den Anfangswert für die Rückgabe der Steuerkomponente in onChange festzulegen, nachdem ein Objekt in eine ID / ein Array von IDs konvertiert wurde. Die Komponente selbst muss abhängig von den ID / IDs, die in sie gesendet werden, das entsprechende Objekt aus allen verfügbaren Elementen auswählen.

    
___ tag123onchange ___ Das onChange-Ereignis wird ausgelöst, wenn der Status eines Elements geändert wird. Viele Sprachen, die mit einer GUI arbeiten, unterstützen eine Form eines Change-Events. Zum Beispiel JavaScript und die JavsScript-Bibliothek jQuery (mit der Funktion .change ()). ___ antwort43904274 ___

Ich bin mir nicht sicher, ob ich das richtig verstanden habe, aber ich würde es gerne versuchen.

Sie möchten, dass der Eingang der Komponente vom folgenden Typ ist:

%Vor%

Sie möchten jedoch, dass die Ausgabe der Komponente nur die String-ID des ausgewählten Elements ist.

Ich würde argumentieren, dass dieser Datenfluss ein bisschen peinlich ist. Während der Initialisierung ist preparedComponent ein object , aber wenn ein Element ausgewählt ist, möchten Sie es in ein string umwandeln. Abgesehen von der Frage der Typsicherheit fühlt es sich einfach nicht intuitiv an.

Stellen Sie sich zum Vergleich vor, dies mit ngModel und einer Texteingabe zu tun:

%Vor%

Möchten Sie ein Objekt übergeben und eine Zeichenfolge zurückgeben, wenn der Benutzer tippt? Wahrscheinlich nicht.

Aber nehmen wir an, dass es aus irgendeinem Grund so sein muss. Sie haben entweder die ng2-select -Implementierung von ControlValueAccessor geändert oder eine eigene Komponente erstellt, die ControlValueAccessor und wraps ng2-select implementiert. (Ich kann nicht sagen, was du in deiner Frage getan hast). Jetzt rufen Sie this.onChange(val.id) auf, wenn ein Element ausgewählt ist und die übergeordnete Komponente mit der String-ID aktualisiert wird.

Dann haben Sie ein separates Problem bemerkt, nämlich dass ng2-select ein Änderungsereignis während der Initialisierung auslöst, wenn Sie einen ausgewählten Wert vordefinieren. Das ist seltsam, weil der Benutzer noch nicht mit der Auswahlsteuerung interagiert hat. Sie haben versucht, preparedComponent zu initialisieren, indem Sie setValue in Ihrem Formularsteuerelement mit emitEvent: false aufgerufen haben, aber ich nehme an, das hat nicht funktioniert, weil es möglicherweise verhindert hat, dass bei der Initialisierung Ihrer Daten% co_de ein Änderungsereignis ausgegeben wurde % hat die zweite Änderung Ihrer Daten sofort vorgenommen.

Sie haben also stattdessen daran gearbeitet, indem Sie bis zum ersten Update von ng2-select gewartet haben, um die Elternkomponente auf ein neues Objekt zu aktualisieren, und dann (mit ng2-select ) überschreiben Sie sie mit der tatsächlich gewünschten String-ID. Dadurch bleibt setTimeout mit einer Zeichenfolge auf dem neuesten Stand, löst jedoch nicht das Problem, dass der Änderungsereignis ausgelöst wird, selbst wenn der Benutzer nicht mit dem Steuerelement interagiert hat. (Übrigens, wenn Sie preparedComponent mit Ihrer eigenen Komponente einpacken, dann bin ich nicht sicher, warum Sie ng2-select part machen müssten, weil Sie nicht schon eine andere Funktion haben, die setTimeout aufruft, wenn this.onChange(val.id) informiert Sie über ein neues ausgewähltes Element, wie ich im vorherigen Absatz erwähnt habe?)

Da ich nicht sagen kann, ob Sie ng2-select direkt ändern oder es mit Ihrer eigenen Komponente umschließen:

Wenn Sie ng2-select ändern, suchen Sie einfach nach der Methode ng2-select und entfernen Sie den Code, der ein Ereignis auslöst? Auf diese Weise aktualisiert es das DOM, wenn Sie einen Wert vordefinieren, überschreibt jedoch nicht Ihren Wert.

Wenn Sie writeValue mit Ihrer eigenen Komponente umschließen, ändern Sie einfach Ihre ng2-select -Methode, um ein Flag zu speichern, wenn writeValue gerade ein Ereignis auslöst, also können Sie es ignorieren:

%Vor%

Und dann in Ihrer Funktion, die auf ein neues ausgewähltes Element reagiert:

%Vor%     
___ qstntxt ___

In meinem Angular (4 + Typescript) Projekt habe ich bereits eine vorbereitete Komponente verwendet (es ist nicht wirklich wichtig, was die Erweiterung von ControlValueAccessor ist, aber wenn das wichtig ist, habe ich ng2-select verwendet), was ich besser wollte UX und schöneres Aussehen. Nach dem Einbinden in meine Formular-Komponente, die reaktive Formulare verwendet, habe ich gesehen, dass ich beim Submit ein Objekt (basierend auf der Klasse SelectItem, das in der vorbereiteten Komponente verwendet wird) zurückgewinnen kann, um ausgewählte Objekte zu verwalten - so:

%Vor%

Da die Komponente im Grunde genommen nur ein Ersatz für die standardmäßige Auswahlsteuerung ist, erwartete ich, dass ich eine ID des ausgewählten Elements, das als String gebildet wurde, zurückbekommen werde - wie folgt:

%Vor%

Nachdem ich erfahren habe, was ControlValueAccessor tatsächlich ist und wie es funktioniert, habe ich die Art und Weise geändert, wie es beim Senden (oder besser beim Ändern des Elements - ng2-select ) an die ID eines Elements zurückgegeben wird. Das Problem wurde für einige Zeit gelöst, bis ich anfing, vordefinierte Werte (auf Editierinstanz) zu setzen, um Kontrollen anstelle von leeren Werten zu bilden (beim Hinzufügen der Instanz). Ich habe herausgefunden, dass dieses Mal die %code% der Formularsteuerung Werte zuweist, die auf dem basieren, was sie als vordefinierten Wert gesendet hat. Also für den Fall, dass ich einen vordefinierten Wert als ... gesendet habe.

%Vor%

... das war auch der Wert in Objekt beim Senden, genau wie im ersten Codebeispiel oben. Ich habe einen Workaround dafür gemacht, um den richtigen Wert für die Steuerung mit %code% direkt nach dem Aufruf von %code% zu vergeben. Das war ein wirklich unpassender Weg, aber ich konnte nichts anderes herausfinden:

%Vor%

Und das hat auch soweit geklappt, dass ich nicht mit der Anmeldung bei %code% der Formularsteuerung begonnen habe. Das Problem ist, dass bei jeder Zuweisung eines vordefinierten Werts zur vorbereiteten Komponente auch der Wert, der nach dem Senden verwendet wird, an die Abonnenten zurückgesendet wird, auch wenn %code% verwendet wird.

Das sind also die Dinge, die ich mit vorbereiteten Komponenten irgendwie behandelt haben möchte, da ich den richtigen Wert aus der Kontrolle beim Senden bekommen möchte und ich keine Änderung an Abonnenten ausgeben lassen soll, bis der Wert wirklich nicht geändert, nicht nur ersetzt wird als vordefinierter Wert. Irgendeine Idee, wie man damit umgeht, wird geschätzt.

    
___ qstnhdr ___ Angular 4 ControlValueAccessor-Wert beim Senden und Wert ändert Ereignisse ___
Frank Modica 10.05.2017, 23:41
quelle
0

Grundsätzlich stellte sich die Frage, ob es möglich ist, verschiedene Werttypen als Anfangswert an eine Steuerkomponente zu senden, die mit der Methode writeValue behandelt werden. Dieser sollte dann den Wert in eine String-ID oder ein Array von String-IDs umwandeln, je nachdem, welcher Typ ausgewählt ist - Einzelwert oder mehrere Werte. Wie Frank in seiner Antwort sagte, ist es etwas peinlich, dies zu tun und onChange mit setTimeout Workaround aufzurufen.

Die Lösung besteht also darin, den Anfangswert für die Rückgabe der Steuerkomponente in onChange festzulegen, nachdem ein Objekt in eine ID / ein Array von IDs konvertiert wurde. Die Komponente selbst muss abhängig von den ID / IDs, die in sie gesendet werden, das entsprechende Objekt aus allen verfügbaren Elementen auswählen.

    
user1257255 17.05.2017 04:41
quelle