Jul 212007
 

Moderne Web-Anwendungen setzen Ajax ein um die Usability zu verbessern – das weiß doch jedes Kind! Eine tolle Sache zur Verbesserung der Usability ist es, für kurze Benutzerinteraktionen einen Popup-Dialog einzublenden, der vom Benutzer einfach wieder geschlossen werden kann. Unter Umständen besteht der Popup aus einer Folge von Dialogen (Wizard-Stil). Der Popup soll kein neues Browser-Fenster sein, sondern per Div über der aktuellen Seite als modaler Dialog “schweben”. Dieser Artikel zeigt eine angenehme Lösung für derartige Popup-Wizard-Dialoge unter Verwendung von Java Server Faces (JSF) und Ajax4JSF (A4J).


Popup-Dialoge sollte insbesondere dann angewendet werden, wenn der Kontext der gerade angezeigten Seite für den Anwender bei der Interaktion im Popup relevant ist. Ein Beispiel: Die aktuelle Seite (Kontext) zeigt eine Liste von Einträgen. Über ein Popup kann der Anwender einen neuen Eintrag in der Liste anlegen. Für die Erstellung des Eintrags kann er auf die aktuelle angezeigte Seite schauen – der Popup-Dialog lässt sich über dessen Titelleise verschieben und gibt den Blick auf die Liste frei. Der Anwender kann den Popup-Dialog über das gewohnte Icon rechts oben schließen. Der Inhalt des Popup-Dialogs wird – beim erstmaligen Anzeigen und beim Dialogwechsel – per Ajax geladen. Daraus resultiert ein besseres Benutzergefühl und verminderte Last auf dem Server (es muss nicht die ganze Seite gerendert werden, nur der Popup-Div-Inhalt).

Zur Umsetzung des Popup-Dialogs selbst verwenden wir die sensationelle Rich Faces JSF-Komponentenbibliothek. Es wird die modalPanel-Komponente verwendet. Auf der Facelets JSF-Seite wird das zunächst nicht sichtbare Popup wie folgt eingebunden:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
    xmlns:rich="http://richfaces.ajax4jsf.org/rich">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="css/richFaces.css" />
</head>

<body>
<f:view contentType="text/html">

    <!-- page content (context) -->
    <p>Hello World</p>

    <rich:modalPanel id="mpWizard" width="600" height="300" zindex="2000"
        resizeable="false" moveable="true">
        <f:facet name="header">Titel des Popups</f:facet>
        <f:facet name="controls">
            <h:graphicImage value="/img/icons/closePanel.png"
                style="cursor:pointer"
                onclick="Richfaces.hideModalPanel('mpWizard')" />
        </f:facet>
        <h:panelGroup id="wizardPanelGroup">
            <a4j:include viewId="/wizardLoading.xhtml" />
        </h:panelGroup>
    </rich:modalPanel>

</f:view>
</body>
</html>

Der Inhalt des Popup-Dialogs wird mittels “a4j:include” eingebunden. Dadurch ist es möglich, dass innerhalb der eingebundenen Seite navigiert (Wizard) werden kann. Der initiale Inhalt des Popups ist eine Seite auf der eine schickes Ajax-Loading-Icon zu sehen ist. Wie man ein solches Icon am besten erstellt, offenbart dieser Artikel.

Jede Inhaltsseite (also auch “wizardLoading.xhtml”) muss folgenden Block enthalten um eine Javascript-Funktion zu rendern (ins server-generierte HTML). Diese Javascript-Funktion wird aufgerufen um die erste Inhaltsseite (nach der Ladeseite) des Wizard-Dialoges mittels Ajax4JSF zu laden. Die Seite “wizardLoading.xhtml” kann also wie folgt aussehen:

<h:form id="addPresentIdeaForm" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:a4j="https://ajax4jsf.dev.java.net/ajax">

    <a4j:region id="showWizardPopupRegion">
        <a4j:jsFunction name="showWizardPopup" action="showWizardPopup"
            reRender="wizardPanelGroup" />
    </a4j:region>

    <a4j:status for="showWizardPopupRegion" layout="block">
        <f:facet name="start">
            <!-- loading image goes here -->
        </f:facet>
        <f:facet name="stop"></f:facet>
    </a4j:status>

</h:form>

Ein Link in der GUI zum Öffnen des Popup-Dialog-Panels wird durch folgenden JSF-Code erzeugt:

<h:outputLink value="#" onclick="Richfaces.showModalPanel('mpWizard');showWizardPopup()">Wizard anzeigen

</h:outputLink>

Durch das Aufrufen der Javascript-Funktion “showWizardPopup” wird server-seitig eine Faces-Navigationsregel für die Action “showWizardPopup” ausgeführt. Es wird zur ersten Seite (zum Bsp. “wizardFirst.xhtml”) navigiert. Die Action wird durch ein Ajax-Request ausgelöst. Der Inhalt der neuen Seite wird gerendert (HTML erzeugt) und per Ajax-Antwort an den Web-Browser-Client zurückgesendet. Im Browser wird der Inhaltsbereich des Popup-Wizards aktualisiert (“wizardPanelGroup”).

Auf den einzelnen Seiten des Wizards kann mittels “a4j:commandLink, “a4j:commandButton”, etc. zu anderen Seiten navigiert werden, die innerhalb des Wizard-Popups angezeigt werden sollen. Es muss lediglich das Attribut “rerender” am A4J-Tag auf “wizardPanelGroup” gesetzt werden.

Soll eine Navigationsregel aus dem Popup ausbrechen und eine neue Seite im Browser angezeigt werden, so muss in der entsprechenden JSF-Navigationsregel das Element “<redirect/>” angegeben werden.

Der Anwender kann den Wizard zu jedem Zeitpunkt über das Icon rechts in der Titelleiste schließen. Wird das Popup erneut geöffnet, so wird die Javascript-Funktion “showWizardPopup” aufgerufen und die erste Seite des Wizards geladen. Dies soll absichern, dass ein einmal geschlossener Wizard beim Wiederöffnen nicht einen Dialog mitten aus der Dialogabfolge anzeigt (ohne zurück zur ersten Seite des Wizards zu springen).

Denkbar wäre hier noch das Unsichtbarmachen des Inhalts vom Popup beim Schließen des Popup-Dialogs. Wird der Popup neu geöffnet und die erste Seite per Ajax geladen so ist der alte Inhalt des Popups nicht sichtbar.

Ich könnte mich jetzt noch weiter an den Details der Lösung austoben, doch ich denke, der Kern dieser Vorgehensweise ist durch den Artikel ausreichend gut vermittelt. :-)

Mittels der hier vorgestellten Lösung ist es mögich auf relativ einfache und klare Weise Popup-Wizarddialoge mit Java Server Faces zu erstellen. Hier noch einmal der Hinweis: Die übermäßige Verwendung von Popups kann natürlich die Usability einer Web-UI zerstören. Gezielt eingesetzt, wirken Wizard-Popups jedoch wahre Wunder für die Anwender- / Kundenzufriendenheit.

  2 Responses to “Wizard Popup-Divs mit Ajax4JSF”

  1. Hi Marc,

    I am new to jsf and working at the moment on a wizard with a4j:include and rich:modalpanels, like your above tutorial. I was following the tutorial from http://www.jboss.org/file-access/default/members/jbossrichfaces/freezone/docs/devguide/en/faq/faq.html#Organizewizards The problem with this tutorial was as you mentioned in your tutorial “dass ein einmal geschlossener Wizard beim Wiederöffnen nicht einen Dialog mitten aus der Dialogabfolge anzeigt” After looking through the internet i came to your site. You explain that you solved it through calling the javascript function “showWizardPopup” everytime you call the modalpanel. Can you please tell me what this javascript does and if possible a little explanation would help me alot.

    Es werde auch in ordnung wenn du mir auf deutsch antwortest.

    Your help is highly appreciated.

    choesang

  2. Hi Choesang,

    the javascript function “showWizardPopup” is generated into the html by the jsf tags [ ]. This javascript function will launch the jsf action “showWizardPopup” at server side. The jsf framework will look up what jsf page to display in the “a4j:include” by examining the navigation rules. Because of the javascript function (actually the form which is submitted) being inside the page included by “a4j:include”, only the included page in the model panel is “navigated”. The attribute [ reRender=”wizardPanelGroup” ] at “a4j:function” tells that the modal panel wich has id “wizardPanelGroup” should be rerendered. When rerendering, the html is transported as http response in json format back from server to the browser. Then the block containing the modal panel is updated and new page (start page of the modal panel) is displayed.

    I hope, i could help you.

    Regards,
    Marc

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>