Kwiecień
21
2009

AJAX i JBoss Seam

Słowa kluczowe: | Kategorie: Seam Framework
No Gravatar

Często gdy użytkownik wykonuje jakąś operację na formularzu, zmienia się niewielki fragment strony. Jednak z powodu sposobu renderowania dokumentów html, w takiej sytuacji odświeżana jest cała jego zawartość. Stosunkowo niedawno powstał nowy sposób ładowania informacji na stronę – AJAX.

Seam pozwala w prosty sposób używać tego rozwiązania w aplikacjach internetowych, co też zamierzam dzisiaj pokazać. W tym celu posłużę się napisaną uprzednio konwersacją, a właściwie odpowiadającym jej plikiem XHTML:


<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:s="http://jboss.com/products/seam/taglib"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:rich="http://richfaces.org/rich"
    template="layout/template.xhtml">

<ui:define name="body">

    <rich:panel>
        <f:facet name="header">
            sampleConversation
        </f:facet>

        <div class="dialog">
            <div class="prop">
                <span class="name">Value</span>
                <span class="value">
                    #{SampleConversation.value}
                </span>
            </div>
        </div>

        <div style="clear:both"/>

    </rich:panel>

    <h:form id="SampleConversation">
        <div class="actionButtons">
            <h:commandButton id="begin" value="Begin"
                action="#{SampleConversation.begin}"
                rendered="#{not conversation.longRunning}"/>
            <h:commandButton id="inc" value="Increment"
                action="#{SampleConversation.increment}"
                rendered="#{conversation.longRunning}"/>
            <h:commandButton id="end" value="End"
                action="#{SampleConversation.end}"
                rendered="#{conversation.longRunning}"/>
        </div>
    </h:form>

</ui:define>

</ui:composition>

W tej chwili każdorazowe naciśnięcie przycisku skutkuje przeładowaniem całej zawartości strony. Dlatego też trzeba dodać parę elementów AJAX, aby przyciski powodowały jedynie pobranie nowych danych w miejscu gdzie się one zmieniają.

Na początku trzeba dodać definicję nowej przestrzeni nazw do elementu ui:composition (xmlns:a4j="http://richfaces.org/a4j"):


<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:s="http://jboss.com/products/seam/taglib"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:rich="http://richfaces.org/rich"
    xmlns:a4j="http://richfaces.org/a4j"
    template="layout/template.xhtml">

Teraz muszę zaznaczyć fragment strony, który ma być odświeżany po wciśnięciu każdego z przycisków. W przypadku Begin muszę ponownie wyświetlić widoczne przyciski:


<div class="dialog">
    <div class="prop">
        <span class="name">Value</span>
        <span class="value">
            <a4j:outputPanel id="valueOutput">
                #{SampleConversation.value}
            </a4j:outputPanel>
        </span>
    </div>
</div>

Dla Increment należy odświeżyć wartość:


<h:form id="SampleConversation">
    <div class="actionButtons">
        <a4j:outputPanel id="buttonsOutput">
            <h:commandButton id="begin" value="Begin"
                action="#{SampleConversation.begin}"
                rendered="#{not conversation.longRunning}"/>
            <h:commandButton id="inc" value="Increment"
                action="#{SampleConversation.increment}"
                rendered="#{conversation.longRunning}"/>
            <h:commandButton id="end" value="End"
                action="#{SampleConversation.end}"
                rendered="#{conversation.longRunning}"/>
        </a4j:outputPanel>
    </div>
</h:form>

Ponieważ przycisk End powoduje przejście na stronę home.seam, nie muszę się nim przejmować.

Pozostało jeszcze takie skonfigurowanie przycisków, aby odświeżały jedynie wybrany fragment strony. Jednak h:commandButton nie posiada takiej funkcji – należy użyć znacznika a4j:commandButton z wartością atrybutu reRender równą wartości id odświeżanego panelu a4j:outputPanel:


<a4j:commandButton id="begin" value="Begin"
    action="#{SampleConversation.begin}"
    rendered="#{not conversation.longRunning}"
    reRender="buttonsOutput"/>
<a4j:commandButton id="inc" value="Increment"
    action="#{SampleConversation.increment}"
    rendered="#{conversation.longRunning}"
    reRender="valueOutput"/>

I to już wszystko. Z początku różnica w działaniu może nie być zauważalna, ale wystarczy na początku dokumentu dodać jakiś duży obrazek, aby korzyści z wykorzystania AJAX były oczywiste:

<ui:define name="body">
    <h:graphicImage value="http://upload.wikimedia.org/wikipedia/commons/3/39/Tux-peluche.jpg"/>

AJAX można z powodzeniem zastosować także na innych stronach. Na przykład doskonale nadaje się do przeglądania długiej listy rekordów tabeli. Ale o tym napiszę już innym razem.

Napisz Komentarz

*