Univention Bugzilla – Bug 26214
MultiInput-Widgets informieren Form nicht über erfolgreiche Initialisierung
Last modified: 2013-07-19 11:31:44 CEST
Created attachment 4209 [details] Teilfix mit Debugausgaben Es senden nicht alle Widgets ein onValuesLoaded-Event. Betroffen sind einige/alle MultiInput-Widgets, die dynamisch Daten nachladen. Eine Teilimplementierung mit Debug-Ausgabe hängt als Patch an. +++ This bug was initially created as a clone of Bug #25630 +++ Wenn Änderungen an einem Objekt vorgenommen werden und ohne Speicherung zur Übersicht zurückgewechselt wird sollte eine Warnung kommen, die darauf hinweist.
umc/widgets/Form.js geht davon aus, dass alle Widgets ein onValuesLoaded zurückgeben, wenn diese fertig gerendert sind und alle Werte geladen wurden. In Bug 25630 wurden in diesem Moment die aktuellen Formularwerte gespeichert, um später z.B. die Differenz zu den Initialwerten ermitteln zu können. Allerdings emittieren die MultiInput-Widgets kein onValuesLoaded, so dass bei der Verwendung von dynamischen Widgets (ComboBox) zu früh angenommen wurde, es wäre alles geladen. Die Kopie der Initialwerte war damit unvollständig. Der Patch konnektiert sich in MultiInput an das onValuesLoaded aller Kindwidgets und fordert diese auf, ihre Werte zu laden. Ist das Event von allen Kindern eingetroffen, wird das Event von MultiInput selbst emittiert. Der Patch behebt das Problem noch nicht vollständig, da nicht alle Kindwidgets ein Event senden (vermutlich immer dann, wenn dynamisch eine leere Liste nachgeladen wurde und somit praktisch kein Wert zu setzen war).
UCS 3.1 will be the next release.
Beim Bearbeiten dieses Bugs ist folgender komischer Bug aufgetreten: http://bugs.dojotoolkit.org/ticket/16209 Als Workaround habe ich eine händisches Kopieren aller Konstruktor-Parameter in umc/widgets/LabelPane:constructor eingebaut. Der Fehler hatte zur Folge, dass in einigen Fällen die Sprach-Auswahlbox des Login-Dialogs nicht zu sehen war und das manchmal das Suchformular von UDM-Modulen nicht initialisiert war.
Created attachment 4727 [details] Patch für umc-frontend
Created attachment 4728 [details] Patch für umc-module-udm
Anbei eine erste Version, die es über eine neuen Methode ready() ermöglicht zu warten bis alle Lade-Aktionen fertig sind, zu einem beliebigen Zeitpunkt (Initialisierung oder später). ready() gibt ein Deferred-Objekt zurück. In meinen Tests hat dies dann auch mit UDM funktioniert. In tests/depends.html wurde das Deferred, welches von der ready()-Method des Formulars zurückgegeben wurde, allerdings noch nicht komplett resolved, Test über: > form._allReady.forEach(function(i, idx) { if (i && !i.isFulfilled()) { console.log(idx) } } )
Der Patch wurde noch etwas ausgebaut. Jetzt funktionieren ready auch wenn neue Werte gesetzt werden, die das Laden von neuen Listen-Werte auslösen. Das zurück gegebene Deferred wartet so lange bis das Listen-Widget aktualisiert wurde. Das UDM-UMC-Modul wurde auch leicht angepasst. univention-management-console-frontend (2.0.139-1) unstable; urgency=low . * added ready() methods to widgets for asynchronous notification; Bug #26214 univention-management-console-module-udm (3.0.39-1) unstable; urgency=low . * use Form::ready(), adapted the modules startup handling; Bug #26214
In Form.js 303 » » » » » » jwidget.ready ? jwidget.ready() : null; fehlt hier nicht ein return?
(In reply to comment #8) > In Form.js > 303 » » » » » » jwidget.ready ? jwidget.ready() : null; > > fehlt hier nicht ein return? Habe ich hinzugefügt in rev36673.
Der Fehler konnte nicht mehr reproduziert werden und insgesamt macht ready() einen sehr robusten Eindruck. Dummerweise ist das kein Beweis für irgend etwas in einer asynchronen Welt. Ich konnte in den Formularen, so wie wir sie nutzen, keinen Fehler feststellen, aber eine Analyse des Quellcodes lässt mich befürchten, dass wir nur "Glück" haben. Der Bug wird REOPENED, nicht weil ich wirklich einen handfesten Fehler gefunden habe, sondern, weil ich die Aufmerksamkeit auf ein mögliches Problem lenken will (und der Bug soll dann - selbst wenn keine Änderungen mehr vorgenommen werden, weil das Problem nur theoretisch aufzutreten scheint - in diesem Bewusstsein geschlossen werden). Das Problem sind meiner Meinung nach diese Zeilen in einigen Widgets: if (this._readyDeferred.isFulfilled()) { this._readyDeferred = new Deferred(); } Szenario: form = new Form({widgets: widgets}) form.ready().then(function(){...}) -> Jede Menge Deferreds, man wartet auf alle. In der Zwischenzeit aber dummerweise das (vielleicht "manuell" ausgeführt): widgets[0]._loadValues() // new Deferred() Dann erst: widgets[0]._setValues() // deferred.resolve() => form.ready() mag ab hier sogar funktionieren, aber die erste Funktion würde meiner Meinung nach nie ausgeführt werden. Kann sowas passieren? Kann mich wer beruhigen?
Außerdem fehlt ein Changelog Eintrag.
(In reply to comment #10) > Der Fehler konnte nicht mehr reproduziert werden und insgesamt macht ready() > einen sehr robusten Eindruck. Dummerweise ist das kein Beweis für irgend etwas > in einer asynchronen Welt. Ich konnte in den Formularen, so wie wir sie nutzen, > keinen Fehler feststellen, aber eine Analyse des Quellcodes lässt mich > befürchten, dass wir nur "Glück" haben. > > Der Bug wird REOPENED, nicht weil ich wirklich einen handfesten Fehler gefunden > habe, sondern, weil ich die Aufmerksamkeit auf ein mögliches Problem lenken > will (und der Bug soll dann - selbst wenn keine Änderungen mehr vorgenommen > werden, weil das Problem nur theoretisch aufzutreten scheint - in diesem > Bewusstsein geschlossen werden). > > Das Problem sind meiner Meinung nach diese Zeilen in einigen Widgets: Guter Hinweis. Das sollte kein Problem sein... ich habe die nächsten Zeilen einmal kommentiert. Bitte noch einmal verifizieren. > if (this._readyDeferred.isFulfilled()) { this._readyDeferred = new Deferred(); > } > > Szenario: > form = new Form({widgets: widgets}) > form.ready().then(function(){...}) > -> Jede Menge Deferreds, man wartet auf alle. > > In der Zwischenzeit aber dummerweise das (vielleicht "manuell" ausgeführt): > widgets[0]._loadValues() // new Deferred() (a) Wenn das readyDeferred beendet ist, würde ein neues erzeugt werden. → dann ist das readyDeferred in form.ready() aber bereits resolved und alles ist gut. Es wurde sicher gestellt (sollte zumindest), dass am Anfang eines Widgets das Deferred-Objekt angelegt wird, so dass es nach new Form(...) existiert (und nicht resolved ist, wenn etwas geladen wird). (b) Wenn das Deferred noch nicht resolved ist, wird auch kein neues angelegt. Das ist ok. Das bisherige readyDeferred wird nicht überschrieben und in form.ready() wird weiterhin darauf gewartet. Ist das ungefähr verständlich? > Dann erst: > widgets[0]._setValues() // deferred.resolve() > > => form.ready() mag ab hier sogar funktionieren, aber die erste Funktion würde > meiner Meinung nach nie ausgeführt werden. > > > Kann sowas passieren? Kann mich wer beruhigen? Sollte also alles ok sein :) . Changelog-Eintrag wurde hinzugefügt.
Ist klar, verstanden. Erklärt auch, warum es funktioniert...
UCS 3.1-0 has been released: http://forum.univention.de/viewtopic.php?f=54&t=2125 If this error occurs again, please use "Clone This Bug".