tutorials.de Buch-Aktion 05/2012
Seite 1 von 2 12 LetzteLetzte
ERLEDIGT
NEIN
ANTWORTEN
15
ZUGRIFFE
2056
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    MadM MadM ist offline Mitglied Bronze
    Registriert seit
    Mar 2005
    Ort
    Darmstadt
    Beiträge
    39
    Hi Folks,

    ich arbeite an einer JSF(1.2)-Anwendung mit RichFaces 3.3.2. Ich will den Benutzer warnen, falls er ein Formular verlässt (d.h. einen anderen Menüpunkt anwählt), ohne seine Änderungen zu speichern.
    Knackpunkt: Wie stelle ich fest, ob er was geändert hat? Ich habe kein eindeutiges Ergebnis googeln können. Hier und da fällt mal das Stichwort onBeforeUnload...

    Szenario:
    Menü verwendet MenuBean (request-scoped)
    Formular verwendet CustomerBean (request-scoped)
    Context-Daten (über den angemeldeten User, seine Berechtigungen etc.) werden in ContextBean (session-scoped) verwaltet.

    Danke für die Hilfe
    Gruß
    Matthias
     

  2. #2
    MadM MadM ist offline Mitglied Bronze
    Registriert seit
    Mar 2005
    Ort
    Darmstadt
    Beiträge
    39
    *PUSH*

    Hat denn wirklich niemand schon einmal ein vergleichbares Szenario gehabt? Oder zumindest einen Lösungsansatz?

    Gruß
    Matthias
     

  3. #3
    Avatar von Bexx
    Bexx Bexx ist offline Programmer
    Registriert seit
    Feb 2009
    Ort
    Saarbrooklyn
    Beiträge
    222
    Eigentlich ist es doch ganz einfach...
    Du hast zwei Möglichkeiten, die Eine etwas aufwändig: Du kannst die Werte aus der DB mit den tatsächlichen Werten in den Variablen
    vergleichen ODER:
    du setzt eine boolsche Variable in der Methode, die zwingend aufgerufen wird bei einer Änderung auf true und prüfst dies
    mit einer gerenderten Message in deiner JSP ab...

    LG,

    Bexx

    EDIT:

    Achso, in deiner Save-Methode musst du die Variable natürlich wieder auf false setzen
    Geändert von Bexx (19.01.10 um 14:46 Uhr)
     
    Christopher Columbus didn't need directions, neither do we!

    Alles hat eine Logik. Selbst wenn es keine Logik gibt.

    ***

    NetBeans 7.x, GlassFish v3
    JSF 2.0
    Java EE

  4. #4
    MadM MadM ist offline Mitglied Bronze
    Registriert seit
    Mar 2005
    Ort
    Darmstadt
    Beiträge
    39
    Naja, so einfach ist es dann doch nicht. Das Problem ist doch, überhaupt zu merken, dass der Benutzer das Formular verlässt. Er drückt ja keinen Button innerhalb des Formulars, sondern wählt einfach einen anderen Menüpunkt.
    Ich müsste also die erwähnte boolsche Variable setzen, sobald der Benutzer etwas ändert. Wie soll ich das aber feststellen? Es wird ja kein HTTP-Request abgeschickt, wenn ein Formularfeld geändert wird, und somit auch keine Methode der Managed-Bean aufgerufen. Und selbst wenn, ich will ja nicht in jedem Setter prüfen, ob sich was geändert hat.
    Du erkennst das Problem? Mir fällt dazu nur eine unschöne JavaScript-Lösung (onKey... o.Ä.) ein...
     

  5. #5
    Avatar von Biergamasda
    Biergamasda Biergamasda ist offline Mitglied Brokat
    Registriert seit
    Feb 2005
    Beiträge
    373
    Ich sehe hierbei noch ganz andere Probleme.
    Wie fragst du ab, ob der Benutzer den Browser schließt, eine andere URL eingibt ... ?

    Die meiner Meinung nach klügste Variante so etwas zu realisieren währe ein mitführen von 2 Tabelleneinträgen. Einen für die gespeicherten Informationen, und einen für die ungespeicherten (welche natürlich dynamisch während der Änderung an den Server geschickt werden müssen)

    Wenn der User dann das nächste mal auf die Seite kommt, kannst du diesen darauf hinweisen, dass er nicht gespeicherte Daten etc hat und ob er sich diese ansehen möchte (bzw. diese parallel dazu in der selben maske anzeigen)

    Ein weiteres Poblem ist dann die eindeutige User-Zuordnung. In deinem Fall, wenn ich das richtig verstehe, handelt es sich um registrierte Benutzer, was das ganze enorm erleichtert. Bei "unbekannten" Usern ist das ganze gleich schon blöder.

    Ich hoffe ich konnte dir ein wenig weiterhelfen... wenn auch nicht in die Richtung in die du wolltest.

    Gruß
    Christoph
     

  6. #6
    MadM MadM ist offline Mitglied Bronze
    Registriert seit
    Mar 2005
    Ort
    Darmstadt
    Beiträge
    39
    Also Browser schliessen oder andere URL eingeben halte ich für grob fahrlässig, würde ich unter "selbst schuld" abhaken.
    Die Lösung mit zwei Tabelleneinträgen geht nicht in die Richtung, die ich will. Dann hab ich ja quasi meine "ungespeicherten Daten" doch gespeichert.
    Ich will lediglich den Benutzer warnen, bevor er das Formular mit ungespeicherten Veränderungen verlässt.
    Dieser (ziemlich alte) Post schlägt eine Lösung mittels NavigationHandler vor, allerdings unter Oracles ADF:
    http://plasticscotsman.blogspot.com/...d-changes.html

    Werde ich morgen mal versuchen....
    Geändert von MadM (19.01.10 um 23:53 Uhr)
     

  7. #7
    Avatar von Bexx
    Bexx Bexx ist offline Programmer
    Registriert seit
    Feb 2009
    Ort
    Saarbrooklyn
    Beiträge
    222
    @ Biergamasda

    das wäre dein perfomancetechnischer Tod...
    bei 100 Datensätzen ok, aber wenn wir hier von zehntausenden reden,
    dann ist es absoluter Schwachsinn.

    du könntest zum Beispiel bei bestehenden Datensätzen einen "Ändern" Button einbauen in dem du
    dir merkst, dass der User etwas verändert hat.

    Ohne deinen Quellcode näher zu kennen, den du mir sehr wahrscheinlich nicht zeigen kannst,
    fällt mir spontan auch nichts anderes ein im Moment

    EDIT:
    Der zündende Einfall ist mir grad gekommen...
    du könntest deine InputTextFelder einfach tatsächlich mit einem onclick oder onkeyup event versehen, das diese Variable auf true setzt und
    voila, du weißt ob etwas verändert wurde.
    Dein Link hat die Lösung doch eigentlich auch schon parat, denn wenn du mal genauer nachliest,
    wurde lediglich ursprünglich eine Lösung unter ADF entwickelt, die diese Entwickler auf JSF anwendbar gemacht haben...
    Verstehe nicht, wie du daran vorbeilesen konntest

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    
      ....
        <application>
        ....
        <!-- Fully qualified class name -->
        <navigation-handler>CommitNavigationHandler</navigation-handler>
        ....
        </application>
        ....
    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    
     
        public class CommitNavigationHandler
        extends NavigationHandler
        {
        private NavigationHandler handler = null;
     
        public static final String COMMIT_ENABLED =
        "#{bindings.Commit.enabled}";
     
        public CommitNavigationHandler(NavigationHandler handler)
        {
        super();
        this.handler = handler;
        }
     
        @Override
        public void handleNavigation(FacesContext facesContext,
        String fromAction, String outcome)
        {
        Boolean outstandingChangesWrapper =
        resolveExpressionAsBoolean(CommitNavigationHandler.COMMIT_ENABLED, facesContext);
        if (outcome != null && outstandingChangesWrapper != null &&
        outstandingChangesWrapper.booleanValue())
        {
        // The outcome is not null (so we are navigating away from the current page)
        // and the page has some unsaved changes so display the same page with a
        // message to tell user to either save the changes or reset the form.
        FacesMessage message =
        new FacesMessage("You have uncommitted changes! Please either save or reset.");
        facesContext.addMessage(null, message);
        this.handler.handleNavigation(facesContext, fromAction, null);
        }
        else
        {
        // No changes or it's a postback, do navigation as intended
        this.handler.handleNavigation(facesContext, fromAction, outcome);
        }
        }
     
        private Boolean resolveExpressionAsBoolean(String el, FacesContext fc)
        {
        ValueBinding valueBinding =
        fc.getApplication().createValueBinding(el);
        return (Boolean) valueBinding.getValue(fc);
        }
        }
    HTML-Code:
              <af:commandButton actionListener="#{bindings.Rollback.execute}"
              text="Rollback" disabled="#{!bindings.Rollback.enabled}"
              immediate="true">
              <af:resetActionListener/>
              </af:commandButton>
    Geändert von Bexx (20.01.10 um 08:44 Uhr)
     
    Christopher Columbus didn't need directions, neither do we!

    Alles hat eine Logik. Selbst wenn es keine Logik gibt.

    ***

    NetBeans 7.x, GlassFish v3
    JSF 2.0
    Java EE

  8. #8
    Avatar von Biergamasda
    Biergamasda Biergamasda ist offline Mitglied Brokat
    Registriert seit
    Feb 2005
    Beiträge
    373
    Zitat Zitat von Bexx Beitrag anzeigen
    @ Biergamasda

    das wäre dein perfomancetechnischer Tod...
    bei 100 Datensätzen ok, aber wenn wir hier von zehntausenden reden,
    dann ist es absoluter Schwachsinn.
    Mir ist durchaus klar, dass dies einen enormen Overhead und Redundanz in der Datenbank erzeugen würde.
    Nur währe dies, imo der einzige Weg, wirklich alle Möglichkeiten zu prüfen bzw. zu berücksichtigen. Aber wie von MadM bereits erwähnt werden diese Fälle sowieso ignoriert, demnach bin ich auch der Meinung dass es schwachsinn währe so etwas zu realisieren.

    Wünsche dir trotzdem noch viel Erfolg bei deinen Versuchen, würde mich interessieren wie du das dann realisiert hast.

    MfG
     

  9. #9
    MadM MadM ist offline Mitglied Bronze
    Registriert seit
    Mar 2005
    Ort
    Darmstadt
    Beiträge
    39
    @Bexx
    Ignoriert wird
    a) Browser schliessen und
    b) (manuell) eine andere URL eingeben.
    Das macht der Benutzer mit Absicht und hat es dann nicht anders gewollt.

    Wenn er aber (versehentlich) den Menüpunkt wechselt, ohne zu Speichern, soll er gewarnt werden. Schwachsinn hin oder her, Pflichtenheft ist Pflichtenheft

    @Biergamasda
    Nun ja, die gezeigte Lösung verwendet immer noch ADF (<af:commandButton..), ich sehe nicht wie das ganze mit JSF/RichFaces funktionieren sollte.
    Zudem ist ValueBinding (Zeile 41) deprecated, wobei Application.evaluateExpressionGet() das selbe tun sollte.
    Werde mal noch etwas experimentieren..
     

  10. #10
    Avatar von Sentoo
    Sentoo Sentoo ist offline Mitglied Gold
    Registriert seit
    Jul 2009
    Ort
    Brühl
    Beiträge
    131
    Moinsen,

    habe gestern und heute damit ein wenig rum gespielt und gesucht. Das beste was ich ans Laufen bekomme habe ist folgendes
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    
    <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
    <%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
    <%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
    <html>
    <head>
    <title>Warn for unsaved changes</title>
    </head>
    <body>
    <f:view>
        <a4j:form>
            <h:outputLabel id="label_name" value="Name" for="in_name" />
            <h:inputText id="in_name" value="#{bean.name}"
                onchange="storeChange(true, this)" />
            <br />
     
            <h:outputLabel id="label_email" value="E-Mail" for="in_email" />
            <h:inputText id="in_email" value="#{bean.email}"
                onchange="storeChange(true, this)" />
            <br />
            <a4j:commandButton oncomplete="javascript:changed=false"
                value="Speichern" />
        </a4j:form>
    </f:view>
    </body>
     
    <script language="javascript" type="text/javascript">
        // flag um zu merken, dass etwas geändert wurde.
        var changed = false;
        /*
        Speichert im changed flag, ob eine Eingabe vom Nutzer gemacht wurde. 
        Anschließend wird der Aufruf dieser Methode aus dem entsprechenden Attribut
        des input elements entfernt, um unnötige Aufrufe zu sparen.
        */
        function storeChange(aChanged, aElement) {
            changed = aChanged;
            aElement.setAttribute('onchange', '');
        }
        /*
        Falls das changed flag angibt, dass es ungespeicherte Eingaben gibt, wird
        eine Warnung ausgegeben, ob die Seite verlassen werden soll. Das erfolgt
        über einen Standardmechanismus. Deswegen ist der Text der zurückgegeben
        wird in einem Textblock des Browser eingebettet. Der Haken daran ist, dass
        dabei die Spracheinstellungen des Anwenders respektiert werden. Es kann also
        sein, dass englischer Text von der deutschen Standardwarnung umrahmt ist.
        */
        window.onbeforeunload=function unloadAlert() {
            if(changed) {
                // wird Text zurückgegeben, wird dieser in der Standardwarnung eingebettet.
                // ehrlicherweise wird alles was diese Methode zurückgibt als String geparst.
                return 'Sie haben nicht gespeicherte Eingaben auf dieser Seite. Wenn Sie OK clicken gehen diese Informationen verloren.';
            }
            // ausser null.
            return null;
        }
    </script>
    </html>

    Allerdings erschlägt das wohl zu viel. Nämlich auch diese Fälle
    Ignoriert wird
    a) Browser schliessen und
    b) (manuell) eine andere URL eingeben.
    Das macht der Benutzer mit Absicht und hat es dann nicht anders gewollt.
    Wenn Du so etwas machen möchtest, musst Du tatsächlich einen eigenen Navigation Handler realisieren. Zu dem müsstest Du das JavaScript-Flag transportieren, was vielleicht über a4j:jsFunction ginge. Müsste ich nochmal drüber nachdenken.
    MadM bedankt sich. 

  11. #11
    MadM MadM ist offline Mitglied Bronze
    Registriert seit
    Mar 2005
    Ort
    Darmstadt
    Beiträge
    39
    Das sieht schon mal ganz gut aus, vielen Dank! Werde es morgen auf der Arbeit dann mal selbst ausprobieren.
     

  12. #12
    wahid wahid ist offline Grünschnabel
    Registriert seit
    Mar 2010
    Beiträge
    4
    @Sentoo,

    Deine Lösung finde ich sehr gut, habe aber noch folgende Frage: Bei mir kann das Flag "changed" unter IE (Ver. 8) beim Submit (a4j:commandButton) auf false nicht gesetzt werden, und IE meldet Script-Error auch noch , während unter der beliebten FF alles wunderbar läuft und ich zweifele an dem JS-Event oncomplete, den IE wahrscheinlich nicht kapiert hat !
    Hast Du denselben Fall auch?

    Danke im Voraus


    Zitat Zitat von Sentoo Beitrag anzeigen
    Moinsen,

    habe gestern und heute damit ein wenig rum gespielt und gesucht. Das beste was ich ans Laufen bekomme habe ist folgendes
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    
    <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
    <%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
    <%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
    <html>
    <head>
    <title>Warn for unsaved changes</title>
    </head>
    <body>
    <f:view>
        <a4j:form>
            <h:outputLabel id="label_name" value="Name" for="in_name" />
            <h:inputText id="in_name" value="#{bean.name}"
                onchange="storeChange(true, this)" />
            <br />
     
            <h:outputLabel id="label_email" value="E-Mail" for="in_email" />
            <h:inputText id="in_email" value="#{bean.email}"
                onchange="storeChange(true, this)" />
            <br />
            <a4j:commandButton oncomplete="javascript:changed=false"
                value="Speichern" />
        </a4j:form>
    </f:view>
    </body>
     
    <script language="javascript" type="text/javascript">
        // flag um zu merken, dass etwas geändert wurde.
        var changed = false;
        /*
        Speichert im changed flag, ob eine Eingabe vom Nutzer gemacht wurde. 
        Anschließend wird der Aufruf dieser Methode aus dem entsprechenden Attribut
        des input elements entfernt, um unnötige Aufrufe zu sparen.
        */
        function storeChange(aChanged, aElement) {
            changed = aChanged;
            aElement.setAttribute('onchange', '');
        }
        /*
        Falls das changed flag angibt, dass es ungespeicherte Eingaben gibt, wird
        eine Warnung ausgegeben, ob die Seite verlassen werden soll. Das erfolgt
        über einen Standardmechanismus. Deswegen ist der Text der zurückgegeben
        wird in einem Textblock des Browser eingebettet. Der Haken daran ist, dass
        dabei die Spracheinstellungen des Anwenders respektiert werden. Es kann also
        sein, dass englischer Text von der deutschen Standardwarnung umrahmt ist.
        */
        window.onbeforeunload=function unloadAlert() {
            if(changed) {
                // wird Text zurückgegeben, wird dieser in der Standardwarnung eingebettet.
                // ehrlicherweise wird alles was diese Methode zurückgibt als String geparst.
                return 'Sie haben nicht gespeicherte Eingaben auf dieser Seite. Wenn Sie OK clicken gehen diese Informationen verloren.';
            }
            // ausser null.
            return null;
        }
    </script>
    </html>

    Allerdings erschlägt das wohl zu viel. Nämlich auch diese Fälle


    Wenn Du so etwas machen möchtest, musst Du tatsächlich einen eigenen Navigation Handler realisieren. Zu dem müsstest Du das JavaScript-Flag transportieren, was vielleicht über a4j:jsFunction ginge. Müsste ich nochmal drüber nachdenken.
     

  13. #13
    Avatar von Sentoo
    Sentoo Sentoo ist offline Mitglied Gold
    Registriert seit
    Jul 2009
    Ort
    Brühl
    Beiträge
    131
    Hallo & Willkommen Wahid,

    mit dem IE 8 kenne ich mich noch nicht groß aus. Die Firma für die wir entwickeln setzt auf den IE6 oder FF 3.X.

    Was ich Dir raten kann ist leider nur folgendes:
    Besorg Dir die IE Developer Tools, die sind Kostenfrei: Discovering Internet Explorer Developer Tools

    Wenn ich solche Probleme mit dem FF habe schaue ich mir das im FireBug an. Das gibt es für den IE 6 nicht. Deswegen kann ich Dir nicht viel zu deinem Problem sagen, ausser, dass Du mit den Developer Tools für den IE auch Java Script debuggen kannst. Damit kannst Du Dein Problem einkreisen.
     

  14. #14
    wahid wahid ist offline Grünschnabel
    Registriert seit
    Mar 2010
    Beiträge
    4
    Hallo Sentoo,

    läuft bei dir das Script unter IE6 problemlos? Habe gerade ein Standalone Version geholt (http://www.my-debugbar.com/wiki/IETester/HomePage) und hat auch nicht funktioniert. Leider mit dem Debuggen von Javascript in IE Web Developper kenne ich mich nicht so gut wie genug aus. Falls Dir spontan was einfällt, wäre ich sehr dankbar für Deinen Vorschlag.


    Zitat Zitat von Sentoo Beitrag anzeigen
    Hallo & Willkommen Wahid,

    mit dem IE 8 kenne ich mich noch nicht groß aus. Die Firma für die wir entwickeln setzt auf den IE6 oder FF 3.X.

    Was ich Dir raten kann ist leider nur folgendes:
    Besorg Dir die IE Developer Tools, die sind Kostenfrei: Discovering Internet Explorer Developer Tools

    Wenn ich solche Probleme mit dem FF habe schaue ich mir das im FireBug an. Das gibt es für den IE 6 nicht. Deswegen kann ich Dir nicht viel zu deinem Problem sagen, ausser, dass Du mit den Developer Tools für den IE auch Java Script debuggen kannst. Damit kannst Du Dein Problem einkreisen.
     

  15. #15
    wahid wahid ist offline Grünschnabel
    Registriert seit
    Mar 2010
    Beiträge
    4
    Hi Sentoo,
    Ich habe probiert und probiert, aber scheinbar dass IE das JS bei oncomplete nicht kapiert, was kannst Du mir raten um dieses Problem zu lösen? Danke im Voraus
     

Ähnliche Themen

  1. Antworten: 4
    Letzter Beitrag: 15.11.08, 17:42
  2. Ausführen beim Verlassen der Seite
    Von Paulus120 im Forum PHP
    Antworten: 8
    Letzter Beitrag: 16.10.05, 19:22
  3. Ausführen beim verlassen der Seite.
    Von Paulus120 im Forum Javascript & Ajax
    Antworten: 2
    Letzter Beitrag: 16.10.05, 19:07
  4. Antworten: 7
    Letzter Beitrag: 27.07.05, 07:53
  5. php script beim verlassen der seite ausführen
    Von sevi im Forum Javascript & Ajax
    Antworten: 1
    Letzter Beitrag: 15.12.03, 15:08

Stichworte