Skip to content

5. PrimeFaces bileşen kütüphanesine giriş

5.1. Bir uygulamada PrimeFaces'in yeri JSF

Bu belgenin başında incelediğimiz gibi, bir JSF uygulamasının mimarisine geri dönelim:

JSF sayfaları üç etiket kütüphanesi kullanılarak oluşturulmuştu:

1
2
3
4
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
  • 2. satır: [http://java.sun.com/jsf/html] ad alanındaki <h:x> etiketleri; bunlar HTML etiketlerine karşılık gelir,
  • 3. satır: [http://java.sun.com/jsf/core] ad alanındaki <f:y> etiketleri, bunlar JSF etiketlerine karşılık gelir,
  • 4. satır: [http://java.sun.com/jsf/facelets] ad alanındaki <ui:z> etiketleri; bunlar facelet etiketlerine karşılık gelir.

JSF sayfalarını oluşturmak için, Primefaces bileşenlerine ait dördüncü bir etiket kütüphanesi ekleyeceğiz.

1
2
3
<html xmlns="http://www.w3.org/1999/xhtml"
      ...
xmlns:p="http://primefaces.org/ui">
  • 3. satır: [http://primefaces.org/ui] ad alanındaki <p:z> etiketleri, Primefaces bileşenlerine karşılık gelir.

Görünürde yapılacak tek değişiklik budur. Dolayısıyla bu değişiklik görünümlerde görünür. Olay işleyiciler ve modeller ise JSF ile olduğu gibi kalır. Bu, anlaşılması gereken önemli bir noktadır.

Primefaces bileşenlerinin kullanılması, bu kütüphanedeki çok sayıda bileşen sayesinde daha kullanıcı dostu ve doğal olarak kullandığı AJAX teknolojisi sayesinde daha akıcı web arayüzleri oluşturulmasına olanak tanır. Bu tür arayüzlere zengin arayüzler veya RIA (Zengin İnternet Uygulaması) denir.

Önceki JSF mimarisi, aşağıdaki PF (Primefaces) mimarisine dönüşecektir:

5.2. Primefaces’in sağladığı avantajlar

Primefaces [http://www.primefaces.org/showcase/ui/home.jsf] web sitesi, bir PF sayfasında kullanılabilecek bileşenlerin listesini sunar:

İlerleyen örneklerde, Primefaces'in sunduğu yüzlerce bileşenden ilk ikisini kullanacağız:

  • sunulan yüzlerce bileşenden bazılarını,
  • bunların AJAX yerel davranışları.

Sunulan bileşenler arasında şunlar yer almaktadır:

Örneklerimizde bunlardan sadece on beş kadarını kullanacağız, ancak bu, bir Primefaces sayfasının oluşturulma ilkelerini anlamak için yeterli olacaktır.

5.3. Primefaces'i Öğrenmek

Primefaces, her bir bileşeninin kullanımına ilişkin örnekler sunar. İlgili bağlantıya tıklamanız yeterlidir. Bir örneğe bakalım:

  • [1], [Spinner] bileşenine ait örnek,
  • [2], [Submit] düğmesine tıklandıktan sonra görüntülenen iletişim kutusu.

Burada bizim için üç yenilik var:

  • [Spinner] bileşeni, JSF'te varsayılan olarak mevcut değildir,
  • aynı durum diyalog penceresi için de geçerli,
  • son olarak, [Submit] tarafından tetiklenen POST, AJAX ile çalışır hale getirilmiştir. POST sırasında tarayıcıya dikkatle bakıldığında, kum saati simgesi görünmez. Sayfa yeniden yüklenmiyor. Sadece değiştiriliyor: sayfada yeni bir bileşen, bu örnekte diyalog kutusu, beliriyor.

Tüm bunların nasıl gerçekleştiğine bir göz atalım. Örnekteki XHTML kodu şöyledir:


<h:form>
       <p:panel header="Spinners">
           <h:panelGrid id="grid" columns="2" cellpadding="5">
                <h:outputLabel for="spinnerBasic" value="Basic Spinner: " />
                <p:spinner id="spinnerBasic" value="#{spinnerController.number1}"/>
                <h:outputLabel for="spinnerStep" value="Step Factor: " />
                <p:spinner id="spinnerStep" value="#{spinnerController.number2}" stepFactor="0.25"/>
                <h:outputLabel for="minmax" value="Min/Max: " />
                <p:spinner id="minmax" value="#{spinnerController.number3}" min="0" max="100"/>
                <h:outputLabel for="prefix" value="Prefix: " />
                <p:spinner id="prefix" value="0" prefix="$" min="0" value="#{spinnerController.number4}"/>
           <h:outputLabel for="ajaxspinner" value="Ajax Spinner: " />
           <p:outputPanel>
                   <p:spinner id="ajaxspinner" value="#{spinnerController.number5}">
                      <p:ajax update="ajaxspinnervalue" process="@this" />
               </p:spinner>
               <h:outputText id="ajaxspinnervalue" value="#{spinnerController.number5}"/>
            </p:outputPanel>
           </h:panelGrid>
       </p:panel>
    <p:commandButton value="Submit" update="display" oncomplete="dialog.show()" />
    
    <p:dialog header="Values" widgetVar="dialog" showEffect="fold" hideEffect="fold">
        ...
     </p:dialog>
</h:form>

Öncelikle, klasik JSF etiketlerinin bulunduğunu görelim: 1. satırda <h:form>, 3. satırda <h:panelGrid>, 4. satırda <h:outputLabel>. Bazı JSF etiketleri, PF tarafından devralınmış ve zenginleştirilmiştir: <p:commandButton> 21. satır. Ardından, biçimlendirme amaçlı PF etiketleri bulunur: <p:panel> satır 2, <p:outputPanel> satır 13, <p:dialog> satır 23. Son olarak, giriş etiketleri vardır: <p:spinner> satır 5.

Bu kodu, görünümle karşılaştırarak inceleyelim:

  • [1]'te, 2. satırdaki <p:panel> etiketiyle elde edilen bileşen,
  • [2], 6. ve 7. satırlardaki <p:outputLabel> ve <p:spinner> etiketlerinin birleşimiyle elde edilen giriş alanı,
  • [3]'e, 21. satırdaki <p:commandButton> etiketiyle elde edilen POST düğmesi,
  • [4]'te, 23-25. satırlardaki iletişim kutusu,
  • [5], iki bileşen için görünmez bir kapsayıcıdır. Bu, 13. satırdaki <p:outputPanel> etiketiyle oluşturulur.

AJAX eylemini uygulayan aşağıdaki kodu inceleyelim:


           <h:outputLabel for="ajaxspinner" value="Ajax Spinner: " />
           <p:outputPanel>
                   <p:spinner id="ajaxspinner" value="#{spinnerController.number5}">
                      <p:ajax update="ajaxspinnervalue" process="@this" />
               </p:spinner>
               <h:outputText id="ajaxspinnervalue" value="#{spinnerController.number5}"/>
</p:outputPanel>

Bu kod, aşağıdaki görünümü oluşturur:

  • 1. satır: [1] metnini görüntüler. Aynı zamanda id=ajaxspinner bileşeninin etiketidir (for özniteliği). Bu bileşen, 3. satırdaki bileşendir (id özniteliği),
  • 3-5. satırlar: [2] bileşenini görüntüler. Bu bileşen, #{spinnerController.number5} şablonuna (value özniteliği) bağlı bir giriş/görüntüleme bileşenidir,
  • 6. satır: [3] bileşenini görüntüler. Bu bileşen, #{spinnerController.number5} modeline bağlı bir görüntüleme bileşenidir (value özniteliği),
  • 4. satır: <p:ajax> etiketi, AJAX davranışını spinner'e ekler. Bu bileşenin değeri her değiştiğinde, bu değere sahip bir POST (process="@this" özniteliği) #{spinnerController.number5} modeline gönderilir. Bu işlem tamamlandıktan sonra, sayfa güncellenir (update özniteliği). Bu özniteliğin değeri, sayfadaki bir bileşenin kimliğidir; burada 6. satırdaki bileşenin kimliği kullanılır. update özniteliğinin hedeflediği bileşen, model ile güncellenir. Bu bileşen yine #{spinnerController.number5} olduğundan, spinner değerini alır. Böylece [3] alanı, [2] alanındaki girişleri takip eder.

Burada AJAX davranışı söz konusudur; bu kısaltma, Asynchronous Javascript And XML anlamına gelir. Genel olarak, bir AJAX davranışı şu şekildedir:

  • tarayıcı, JavaScript kodu (AJAX'teki J) içeren bir HTML sayfası görüntüler. Sayfanın öğeleri, DOM (Document Object Model) olarak adlandırılan bir JavaScript nesnesi oluşturur,
  • sunucu, bu sayfayı oluşturan web uygulamasını barındırır,
  • [1]'te, sayfada bir olay meydana gelir. Örneğin, spinner'in artırılması. Bu olay, JavaScript tarafından yönetilir,
  • [2]'te, JavaScript web uygulamasına bir POST işlemi gerçekleştirir. Bunu asenkron bir şekilde yapar (AJAX'teki A). Kullanıcı sayfayla çalışmaya devam edebilir. Sayfa donmaz, ancak gerekirse dondurulabilir. POST, gönderilen değerlere göre sayfa şablonunu günceller; burada şablon #{spinnerController.number5}'dir,
  • [3]'e günceller; web uygulaması, JavaScript'e XML (AJAX'teki X) veya JSON (JavaScript Nesne Notasyonu),
  • [4]'te, JavaScript bu yanıtı kullanarak DOM'teki belirli bir alanı günceller; burada id=ajaxspinnervalue alanıdır.

JSF ve Primefaces kullanıldığında, JavaScript kodu Primefaces tarafından oluşturulur. Bu kütüphane, JQuery JavaScript kütüphanesini temel alır. Aynı şekilde, Primefaces bileşenleri de JQuery ve UI (Kullanıcı Arayüzü) bileşen kütüphanelerindeki bileşenlere dayanmaktadır. Dolayısıyla JQuery, Primefaces’in temelini oluşturmaktadır.

Örneğimize geri dönelim ve şimdi [Submit] düğmesinin POST bileşenini inceleyelim:

POST ile ilişkili kod şöyledir:


<p:commandButton value="Submit" update="display" oncomplete="dialog.show()" />
    
    <p:dialog header="Values" widgetVar="dialog" showEffect="fold" hideEffect="fold">
        <h:panelGrid id="display" columns="2" cellpadding="5">
            <h:outputText value="Value 1: " />
            <h:outputText value="#{spinnerController.number1}" /> 
            
            <h:outputText value="Value 2: " />
            <h:outputText value="#{spinnerController.number2}" /> 
            
            <h:outputText value="Value 3: " />
            <h:outputText value="#{spinnerController.number3}" /> 
            
            <h:outputText value="Value 4: " />
            <h:outputText value="#{spinnerController.number4}" /> 
            
            <h:outputText value="Value 5: " />
            <h:outputText value="#{spinnerController.number5}" /> 
        </h:panelGrid>
     </p:dialog>
                
</h:form>
  • 1. satır: POST, 1. satırdaki düğme tarafından tetiklenir. Primefaces'te, bir POST'i tetikleyen etiketler, varsayılan olarak bir AJAX çağrısı şeklinde bunu gerçekleştirir. Bu nedenle bu etiketler, sunucudan yanıt alındığında güncellenecek alanı belirtmek için bir update özniteliğine sahiptir. Burada güncellenen alan, 4. satırdaki panelGrid'tir. Dolayısıyla POST geri döndüğünde, bu alan modele gönderilen değerlerle güncellenecektir. Ancak bu etiketler, varsayılan olarak görünmeyen bir iletişim kutusunun içindedir. İletişim kutusunu görüntüleyen, 1. satırdaki oncomplete özniteliğidir. Bu olay, POST'in işlenmesi tamamlandığında gerçekleşir. Bu özniteliğin değeri bir JavaScript kodudur. Burada, id=dialog olan diyalog penceresi, yani 3. satırdaki (widgetVar özniteliği) diyalog penceresi görüntülenir,
  • 3. satır: İletişim kutusunun çeşitli özniteliklerini görüyoruz. Ne işe yaradıklarını anlamak için denemeler yapmanız gerekir.

Şablondan bahsettik ancak henüz göstermedik. İşte bu:

public class SpinnerController {

    private int number1;
    private double number2;
    private int number3;
    private int number4;
    private int number5;

     // alıcı ve ayarlayıcılar
...
}

Genel olarak şu şekilde ilerleyebiliriz:

  • kullanmak istediğiniz Primefaces bileşenini belirleyin,
  • örneğini inceleyin. Primefaces örnekleri iyi hazırlanmış ve kolayca anlaşılabilir.

5.4. İlk Primefaces projesi: mv-pf-01

NetBeans ile bir Maven web projesi oluşturalım:

  • [1, 2, 3]: [Web Application] türünde bir Maven projesi oluşturuyoruz,
  • [4]: sunucu Tomcat olacak,
  • [5]'te, oluşturulan proje,
  • [6]'te, [index.jsp] dosyası ve Java paketi siliniyor,
  • [7, 8]'te: proje özelliklerine Java Server Faces desteği eklenir,
  • olarak [9]'e dönüştürün; [Components] sekmesinde PrimeFaces bileşen kütüphanesini seçin. NetBeans, diğer bileşen kütüphaneleri için de destek sunar: ICEFaces ve RichFaces.
  • [10]'te, oluşturulan proje. [11]'te, Primefaces'e olan bağımlılık dikkat çekmektedir.

Basitçe söylemek gerekirse, bir Primefaces projesi, Primefaces bağımlılığı eklenmiş klasik bir JSF projesidir. Hepsi bu kadar.

Bunu anladıktan sonra, kütüphanelerin en son sürümleriyle çalışabilmek için [pom.xml] dosyasını değiştiriyoruz:


    <dependency>
      <groupId>com.sun.faces</groupId>
      <artifactId>jsf-impl</artifactId>
      <version>2.1.8</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.primefaces</groupId>
      <artifactId>primefaces</artifactId>
      <version>3.3</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-web-api</artifactId>
      <version>6.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <repositories>
    <repository>
      <id>jsf20</id>
      <name>Repository for library Library[jsf20]</name>
      <url>http://download.java.net/maven/2/</url>
    </repository>
    <repository>
      <id>primefaces</id>
      <name>Repository for library Library[primefaces]</name>
      <url>http://repository.primefaces.org/</url>
    </repository>
</repositories>

26-30. satırlarda, Primefaces için Maven deposuna dikkat edin. Bu değişiklikleri yaptıktan sonra, bağımlılıkların indirilmesini başlatmak için projeyi derleriz. Böylece [12] projesini elde ederiz.

Şimdi, incelediğimiz örneği yeniden oluşturmaya çalışalım. [index.html] sayfası şu şekilde olur:


<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
  <h:head>
    <title>Spinner</title>
  </h:head>
  <h:body>
    <!-- form -->
    <h:form>
      <p:panel header="Spinners">
        <h:panelGrid id="grid" columns="2" cellpadding="5">
          <h:outputLabel for="spinnerBasic" value="Basic Spinner: " />
          <p:spinner id="spinnerBasic" value="#{spinnerController.number1}"/>
          <h:outputLabel for="spinnerStep" value="Step Factor: " />
          <p:spinner id="spinnerStep" value="#{spinnerController.number2}" stepFactor="0.25"/>
          <h:outputLabel for="minmax" value="Min/Max: " />
          <p:spinner id="minmax" value="#{spinnerController.number3}" min="0" max="100"/>
          <h:outputLabel for="prefix" value="Prefix: " />
          <p:spinner id="prefix" prefix="$" min="0" value="#{spinnerController.number4}"/>
          <h:outputLabel for="ajaxspinner" value="Ajax Spinner: " />
          <p:outputPanel>
            <p:spinner id="ajaxspinner" value="#{spinnerController.number5}">
              <p:ajax update="ajaxspinnervalue" process="@this" />
            </p:spinner>
            <h:outputText id="ajaxspinnervalue" value="#{spinnerController.number5}"/>
          </p:outputPanel>
        </h:panelGrid>
      </p:panel>
      <p:commandButton value="Submit" update="display" oncomplete="dialog.show()" />
      <!-- iletişim kutusu -->
      <p:dialog header="Values" widgetVar="dialog" showEffect="fold" hideEffect="fold">
        <h:panelGrid id="display" columns="2" cellpadding="5">
          <h:outputText value="Value 1: " />
          <h:outputText value="#{spinnerController.number1}" /> 
          <h:outputText value="Value 2: " />
          <h:outputText value="#{spinnerController.number2}" /> 
          <h:outputText value="Value 3: " />
          <h:outputText value="#{spinnerController.number3}" /> 
          <h:outputText value="Value 4: " />
          <h:outputText value="#{spinnerController.number4}" /> 
          <h:outputText value="Value 5: " />
          <h:outputText value="#{spinnerController.number5}" /> 
        </h:panelGrid>
      </p:dialog>
    </h:form>
  </h:body>
</html>

Primefaces etiket kütüphanesinin ad alanını tanımlayan 5. satırı unutmayalım. Projeye, sayfa için şablon görevi gören bean'i ekliyoruz:

  

Bean şu şekildedir:


package beans;

import javax.faces.bean.RequestScoped;
import javax.faces.bean.ManagedBean;

@ManagedBean
@RequestScoped
public class SpinnerController {

  // şablon
  private int number1;
  private double number2;
  private int number3;
  private int number4;
  private int number5;

  // alıcı ve ayarlayıcılar
  ...
}

Sınıf, istek kapsamında (satır 7) bir bean'dir (satır 6). Bir isim belirtilmediğinden, bean, ilk harfi küçük harf olan sınıfın adını alır: spinnerController.

Proje çalıştırıldığında şu sonuç elde edilir:

 

Böylece, Primefaces sitesinden alınan bir örneği nasıl test edeceğimizi göstermiş olduk. Tüm örnekler bu şekilde test edilebilir.

Bundan sonra, yalnızca Primefaces'in belirli bileşenlerine odaklanacağız. Öncelikle, JSF ile incelediğimiz örnekleri ele alacağız ve bazı JSF etiketlerini Primefaces etiketleriyle değiştireceğiz. Sayfaların görünümü biraz değişecek, AJAX davranışını sergileyecekler ancak ilgili bean'lerin değiştirilmesine gerek kalmayacaktır. İleride vereceğimiz her örnekte, sayfaların XHTML kodunu ve ilgili ekran görüntülerini sunmakla yetineceğiz. Okuyucunun, JSF sayfaları ile PF sayfaları arasındaki farkları tespit etmek için örnekleri test etmesi önerilir.

5.5. mv-pf-02 örneği: olay yöneticisi – uluslararasılaştırma – sayfalar arası gezinme

Bu proje, JSF [mv-jsf2-02] projesinin uyarlanmış halidir (2.4. paragraf, sayfa 41):

NetBeans projesi şöyledir:

[index.html] sayfası şöyledir:


<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
  <f:view locale="#{changeLocale.locale}">
    <h:head>
      <title><h:outputText value="#{msg['welcome.titre']}" /></title>
    </h:head>
    <body>
      <h:form id="formulaire">
        <h:panelGrid columns="2">
          <p:commandLink value="#{msg['welcome.langue1']}" action="#{changeLocale.setFrenchLocale}" ajax="false"/>
          <p:commandLink value="#{msg['welcome.langue2']}" action="#{changeLocale.setEnglishLocale}" ajax="false"/>
        </h:panelGrid>
        <h1><h:outputText value="#{msg['welcome.titre']}" /></h1>
        <p:commandLink value="#{msg['welcome.page1']}" action="page1" ajax="false"/>
      </h:form>
    </body>
  </f:view>
</html>

15, 16 ve 19. satırlarda <h:commandLink> etiketleri, <p:commandLink> etiketleriyle değiştirilmiştir. Bu etiket, varsayılan olarak AJAX davranışına sahiptir; bu davranış, ajax="false" özniteliği eklenerek devre dışı bırakılabilir. Dolayısıyla burada, <p:commandLink> etiketleri <h:commandLink> etiketleri gibi davranır: bu bağlantılara tıklandığında sayfa yeniden yüklenecektir.

5.6. Örnek mv-pf-03: Facelets kullanılarak sayfa düzeni oluşturma

Bu proje, [mv-jsf2-09] örneğindeki (2.11. paragraf) facelets şablonlarını kullanarak XHTML sayfalarının oluşturulmasını göstermektedir:

 

NetBeans projesi şöyledir:

  • [1]'te, proje yapılandırma dosyaları JSF,
  • [2]'te, sayfalar XHTML'te,
  • [3]'e, dil değiştirme için destek bean'i,
  • [4]'e mesaj dosyaları,
  • [5] dosyasına, bağımlılıklar.

Proje sayfaları, [layout.xhtml] sayfasını örnek almaktadır:


<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
  <f:view locale="#{changeLocale.locale}">
    <h:head>
      <title>JSF</title>
      <h:outputStylesheet library="css" name="styles.css"/>
    </h:head>
    <h:body style="background-image: url('${request.contextPath}/resources/images/standard.jpg');">
      <h:form id="formulaire">
        <table style="width: 600px">
          <tr>
            <td colspan="2" bgcolor="#ccccff">
              <ui:include src="entete.xhtml"/>
            </td>
          </tr>
          <tr>
            <td style="width: 100px; height: 200px" bgcolor="#ffcccc">
              <ui:include src="menu.xhtml"/>
            </td>
            <td>
              <p:outputPanel id="contenu">
                <ui:insert name="contenu" >
                  <h2>Contenu</h2>
                </ui:insert>
              </p:outputPanel>
            </td>
          </tr>
          <tr bgcolor="#ffcc66">
            <td colspan="2">
              <ui:include src="basdepage.xhtml"/>
            </td>
          </tr>         
        </table>
      </h:form>
    </h:body>
  </f:view>
</html>
  • 9. satır: <f:view> etiketi, sağladığı uluslararasılaştırma özelliğinden yararlanmak amacıyla tüm sayfayı çerçeveler,
  • 15. satır: id'si "form" olan bir form. Bu form, sayfanın ana gövdesini oluşturur. Bu gövdede, yalnızca 28-30. satırlar arasında dinamik bir bölüm bulunmaktadır. Sayfanın değişken kısmı buraya eklenecektir:
  • Yukarıda çerçeveli alan, AJAX çağrıları ile güncellenecektir. Bu alanı tanımlamak için, onu <p:outputPanel> etiketiyle oluşturulan bir Primefaces konteynerine dahil ettik (27. satır). Ve bu konteyner, id özniteliği ile "contenu" olarak adlandırılmıştır. Kendisi de "form" adlı bir konteyner olan bir formun içinde bulunduğu için, dinamik alanın tam adı :form:contenu şeklindedir. İlk : işareti, belgenin kökünden başladığımızı, ardından "form" adlı konteynere, oradan da "contenu" adlı konteynere geçtiğimizi belirtir. AJAX ile ilgili bir zorluk, AJAX çağrısı ile güncellenecek alanları doğru şekilde adlandırmaktır. En basit yol, alınan HTML sayfasının kaynak koduna bakmaktır:

1
2
3
            <td><span id="formulaire:contenu">
                  <h2>Contenu</h2></span>
</td>

Yukarıda, <h:outputPanel> etiketinin bir HTML <span> etiketi oluşturduğu görülmektedir. Bu örnekte, form:içerik (başlangıçtaki : işareti olmadan) ve :form:içerik (başlangıçtaki : işareti ile) göreceli adları aynı nesneyi ifade etmektedir.

Dinamik alanı güncelleyen AJAX çağrılarının (<p:commandButton>, <p:commandLink>) update=":form:içerik" özniteliğine sahip olacağını unutmayalım.

[index.xhtml] sayfası, proje tarafından görüntülenen tek sayfadır:


<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
  <ui:composition template="layout.xhtml">
    <ui:define name="contenu">
      <ui:fragment rendered="#{requestScope.page1 || requestScope.page2==null}">
        <ui:include src="page1.xhtml"/>
      </ui:fragment>
      <ui:fragment rendered="#{requestScope.page2}">
        <ui:include src="page2.xhtml"/>
      </ui:fragment>
    </ui:define>
  </ui:composition>
</html>
  • 8. satırda, [index.xhtml] şablonu, az önce tanıtılan [layout.xhtml] sayfasıdır;
  • 9. satırda ise [index.html] tarafından güncellenen içerik kimliği alanı yer almaktadır. Bu alanda iki parça bulunmaktadır:
    • 11. satırdaki [page1.xhtml] parçası;
    • 14. satırdaki [page2.xhtml] parçası.

Bu iki parça birbirini dışlar.

  • 10. satır: [page1.xhtml] parçası, isteğin page1 özniteliği true olarak ayarlanmışsa veya page2 özniteliği mevcut değilse görüntülenir. Bu durum, bu özniteliklerin hiçbirinin istekte bulunmadığı ilk istekte geçerlidir. Bu durumda, [page1.xhtml] parçası görüntülenir;
  • 11. satırda, isteğin page2 özniteliği true ise [page2.xhtml] parçası görüntülenir

[page1.xhtml] parçası şöyledir:


<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">

  <body>
    <h:panelGrid columns="2">
      <p:commandLink value="#{msg['page1.langue1']}" actionListener="#{changeLocale.setFrenchLocale}" ajax="true" update=":formulaire:contenu"/>
      <p:commandLink value="#{msg['page1.langue2']}" actionListener="#{changeLocale.setEnglishLocale}" ajax="true" update=":formulaire:contenu"/>
    </h:panelGrid>
    <h1><h:outputText value="#{msg['page1.titre']}" /></h1>
     <p:commandLink value="#{msg['page1.lien']}" update=":formulaire:contenu">
      <f:setPropertyActionListener value="#{true}" target="#{requestScope.page2}" />  
    </p:commandLink>
  </body>
</html>

ve şu içeriği görüntüler:

  • 11. ve 12. satırlarda, dili değiştirmek için iki bağlantı bulunmaktadır. Bu iki bağlantı, AJAX (ajax=true) çağrılarını tetikler. Bu, varsayılan ayardır. Dolayısıyla, ajax=true özniteliğini eklememeyi tercih edebiliriz. Bundan sonra bunu yapmayacağız. Bu iki bağlantının, yukarıda çerçeveli olan :form:içerik alanını (update özniteliği) güncellediğine dikkat edelim,
  • 15. satır: Yine :form:içerik alanını güncelleyen bir AJAX gezinme bağlantısı,
  • 16. satır: <h:setPropertyActionListener> etiketini kullanarak page2 özniteliğini isteğe true değeriyle ekliyoruz. Bu işlem, [page2.xhtml] parçasını (aşağıdaki 6. satır) [index.xhtml] sayfasında görüntüleyecektir:

  <ui:composition template="layout.xhtml">
    <ui:define name="contenu">
      <ui:fragment rendered="#{requestScope.page1 || requestScope.page2==null}">
        <ui:include src="page1.xhtml"/>
      </ui:fragment>
      <ui:fragment rendered="#{requestScope.page2}">
        <ui:include src="page2.xhtml"/>
      </ui:fragment>
    </ui:define>
</ui:composition>

[page2.xhtml] parçası da buna benzer:

[page2.xhtml] kodunun içeriği şöyledir:


<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">

  <body>
    <h1><h:outputText value="#{msg['page2.entete']}"/></h1>
    <p:commandLink value="#{msg['page2.lien']}" update=":formulaire:contenu">
      <f:setPropertyActionListener value="#{true}" target="#{requestScope.page1}" />  
    </p:commandLink>
  </body>
</html>

Bu örnekten, ileride kullanmak üzere şu noktaları not edelim:

  • sayfalar için [layout.xhtml] şablonunu kullanacağız,
  • dinamik alan, id:form:içerik ile tanımlanacak ve AJAX çağrılarıyla güncellenecektir.

5.7. mv-pf-04 örneği: veri girişi formu

Bu proje, JSF2 ve [mv-jsf2-03] projelerinin uyarlanmış halidir (bkz. paragraf 2.5):

NetBeans projesi şöyledir:

Yukarıda, [1] içinde, projenin XHTML sayfaları yer almaktadır. Sayfa düzeni, daha önce incelenen [layout.xhtml] şablonu ile sağlanmaktadır. [index.xhtml] sayfası, projenin tek sayfasıdır. Bu sayfa, :form:içerik alanında görüntülenir. Kod şöyledir:


<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
  <ui:composition template="layout.xhtml">
    <ui:define name="contenu">
      <ui:include src="page1.xhtml"/>
    </ui:define>
  </ui:composition>
</html>

Bu sayfa, yalnızca [page1.xhtml] fragmanını görüntüler. Bu fragman, [mv-jsf2-03] örneğinde incelenen formun karşılığıdır. Hatırlanacağı üzere, o örneğin amacı JSF giriş etiketlerini göstermekti. Bu etiketler burada Primefaces etiketleriyle değiştirilmiştir.

PanelGrid

[page1.xhtml] öğelerini biçimlendirmek için <p:panelGrid> etiketini kullanıyoruz. Örneğin, iki dil bağlantısı için:


<!-- diller -->
    <p:panelGrid columns="2">
      <p:commandLink value="#{msg['form.langue1']}" actionListener="#{changeLocale.setFrenchLocale}" update=":formulaire:contenu"/>
      <p:commandLink value="#{msg['form.langue2']}" actionListener="#{changeLocale.setEnglishLocale}" update=":formulaire:contenu"/>
    </p:panelGrid>

Bu, aşağıdaki gibi görüntülenir:

 

<p:panelGrid> etiketinin başka bir biçimi şöyledir:


<p:panelGrid>

      <f:facet name="header">  
        <p:row>  
          <p:column colspan="3"><h:outputText value="#{msg['form.titre']}"/></p:column>  
        </p:row>  
        <p:row>  
          <p:column><h:outputText value="#{msg['form.headerCol1']}"/></p:column>  
          <p:column><h:outputText value="#{msg['form.headerCol2']}"/></p:column>  
          <p:column><h:outputText value="#{msg['form.headerCol3']}"/></p:column>  
        </p:row>  
      </f:facet>        

      <p:row>
        <p:column>
          <h:outputText value="inputText"/>
        </p:column>
        <p:column>
          <h:outputLabel for="inputText" value="#{msg['form.loginPrompt']}" />  
          <p:inputText id="inputText" value="#{form.inputText}"/>
        </p:column>
        <p:column>
          <h:outputText id="inputTextValue" value="#{form.inputText}"/>
        </p:column>
      </p:row>
...
     <f:facet name="footer">
        <p:row>
          <p:column colspan="3">
            <div align="center">
              <p:commandButton value="#{msg['form.submitText']}" update=":formulaire:contenu"/>
            </div>
          </p:column>
        </p:row>
      </f:facet>    
</p:panelGrid>

Tablonun satırları ve sütunları <p:row> ve <p:column> etiketleriyle tanımlanır.

3-12. satırlar tablonun başlığını tanımlar:

 

14-25. satırlar, tablonun bir satırını tanımlar:

 

27-35. satırlar tablonun altbilgisini tanımlar:

 

inputText


      <p:row>
        <p:column>
          <h:outputText value="inputText"/>
        </p:column>
        <p:column>
          <h:outputLabel for="inputText" value="#{msg['form.loginPrompt']}" />  
          <p:inputText id="inputText" value="#{form.inputText}"/>
        </p:column>
        <p:column>
          <h:outputText id="inputTextValue" value="#{form.inputText}"/>
        </p:column>
</p:row>
 

password


<p:row>
        <p:column>
          <h:outputText value="inputSecret"/>
        </p:column>
        <p:column>
          <h:outputLabel for="inputSecret" value="#{msg['form.passwdPrompt']}"/>
          <p:password id="inputSecret" value="#{form.inputSecret}" feedback="true"   
               promptLabel="#{msg['form.promptLabel']}" weakLabel="#{msg['form.weakLabel']}"  
               goodLabel="#{msg['form.goodLabel']}" strongLabel="#{msg['form.strongLabel']}" />  
        </p:column>
        <p:column>
          <h:outputText id="inputSecretValue" value="#{form.inputSecret}"/>
        </p:column>
      </p:row>
  1. satırda, feedback=true özniteliği, şifrenin kalitesi hakkında geri bildirim alınmasını sağlar. [1]

inputTextArea


<p:row>
        <p:column>
          <h:outputText value="inputTextArea"/>
        </p:column>
        <p:column>
          <h:outputLabel for="inputTextArea" value="#{msg['form.descPrompt']}"/>
          <p:editor id="inputTextArea" value="#{form.inputTextArea}" rows="4"/>
        </p:column> 
        <p:column>
          <h:outputText id="inputTextAreaValue" value="#{form.inputTextArea}"/>
        </p:column>
      </p:row>
  1. satırda, <p:editor> etiketi, metni biçimlendirmeye (yazı tipi, boyut, renk, hizalama vb.) olanak tanıyan zengin bir düzenleyici görüntüler. Sunucuya gönderilen, girilen metnin HTML kodudur [2].

selectOneListBox


<p:row>
        <p:column>
          <h:outputText value="selectOneListBox"/>
        </p:column>
        <p:column>
          <h:outputLabel for="selectOneListBox1" value="#{msg['form.selectOneListBox1Prompt']}"/>
          <p:selectOneListbox id="selectOneListBox1" value="#{form.selectOneListBox1}">
            <f:selectItem itemValue="1" itemLabel="un"/>
            <f:selectItem itemValue="2" itemLabel="deux"/>
            <f:selectItem itemValue="3" itemLabel="trois"/>
          </p:selectOneListbox>
        </p:column>
        <p:column>
          <h:outputText id="selectOneListBox1Value" value="#{form.selectOneListBox1}"/>
        </p:column>
      </p:row>
 

selectOneMenu


<p:row>
        <p:column>
          <h:outputText value="selectOneMenu"/>
        </p:column>
        <p:column>
          <h:outputLabel for="selectOneMenu" value="#{msg['form.selectOneMenuPrompt']}"/>
          <p:selectOneMenu id="selectOneMenu" value="#{form.selectOneMenu}">
            <f:selectItem itemValue="1" itemLabel="un"/>
            <f:selectItem itemValue="2" itemLabel="deux"/>
            <f:selectItem itemValue="3" itemLabel="trois"/>
            <f:selectItem itemValue="4" itemLabel="quatre"/>
            <f:selectItem itemValue="5" itemLabel="cinq"/>
          </p:selectOneMenu>
        </p:column>
        <p:column>
          <h:outputText id="selectOneMenuValue" value="#{form.selectOneMenu}"/>
        </p:column>
      </p:row>
 

selectManyMenu


<p:row>
        <p:column>
          <h:outputText value="selectManyMenu"/>
        </p:column>
        <p:column>
          <h:outputLabel for="selectManyMenu" value="#{msg['form.selectManyMenuPrompt']}"/>
          <p:selectManyMenu id="selectManyMenu" value="#{form.selectManyMenu}" >
            <f:selectItem itemValue="1" itemLabel="un"/>
            <f:selectItem itemValue="2" itemLabel="deux"/>
            <f:selectItem itemValue="3" itemLabel="trois"/>
            <f:selectItem itemValue="4" itemLabel="quatre"/>
            <f:selectItem itemValue="5" itemLabel="cinq"/>
          </p:selectManyMenu>
          <p:commandLink value="#{msg['form.buttonRazText']}" actionListener="#{form.clearSelectManyMenu()}" update=":formulaire:selectManyMenu" style="margin-left: 10px"/>
        </p:column>
        <p:column>
          <h:outputText id="selectManyMenuValue" value="#{form.selectManyMenuValue}"/>
        </p:column>
      </p:row>
 
  1. satırda, [Raz] bağlantısının, 6. satırdaki bileşene karşılık gelen :form:selectManyMenu alanını AJAX ile güncellediği görülmektedir. Bununla birlikte, POST AJAX işlemi sırasında formdaki tüm değerlerin gönderildiğini bilmek gerekir. Dolayısıyla, şablonun tamamı güncellenir. Ancak bu şablonla yalnızca :form:selectManyMenu alanı güncellenir.

selectBooleanCheckbox


<p:row>
        <p:column>
          <h:outputText value="selectBooleanCheckbox"/>
        </p:column>
        <p:column>
          <h:outputLabel for="selectBooleanCheckbox" value="#{msg['form.selectBooleanCheckboxPrompt']}"/>
          <p:selectBooleanCheckbox id="selectBooleanCheckbox" value="#{form.selectBooleanCheckbox}"/>
        </p:column>
        <p:column>
          <h:outputText id="selectBooleanCheckboxValue" value="#{form.selectBooleanCheckbox}"/>
        </p:column>
      </p:row>
 

selectManyCheckbox


<p:row>
        <p:column>
          <h:outputText value="selectManyCheckbox"/>
        </p:column>
        <p:column>
          <h:outputLabel for="selectManyCheckbox" value="#{msg['form.selectManyCheckboxPrompt']}"/>
          <p:selectManyCheckbox id="selectManyCheckbox" value="#{form.selectManyCheckbox}">
            <f:selectItem itemValue="1" itemLabel="rouge"/>
            <f:selectItem itemValue="2" itemLabel="bleu"/>
            <f:selectItem itemValue="3" itemLabel="blanc"/>
            <f:selectItem itemValue="4" itemLabel="noir"/>
          </p:selectManyCheckbox>
        </p:column>
        <p:column>
          <h:outputText id="selectManyCheckboxValue" value="#{form.selectManyCheckboxValue}"/>
        </p:column>
      </p:row>
 

selectOneRadio


<p:row>
        <p:column>
          <h:outputText value="selectOneRadio"/>
        </p:column>
        <p:column>
          <h:outputLabel for="selectOneRadio" value="#{msg['form.selectOneRadioPrompt']}"/>
          <p:selectOneRadio id="selectOneRadio" value="#{form.selectOneRadio}" >
            <f:selectItem itemValue="1" itemLabel="voiture"/>
            <f:selectItem itemValue="2" itemLabel="vélo"/>
            <f:selectItem itemValue="3" itemLabel="scooter"/>
            <f:selectItem itemValue="4" itemLabel="marche"/>
          </p:selectOneRadio>
        </p:column>
        <p:column>
          <h:outputText id="selectOneRadioValue" value="#{form.selectOneRadio}"/>
        </p:column>
      </p:row>
 

5.8. Örnek: mv-pf-05: dinamik listeler

Bu proje, JSF2 [mv-jsf2-04] projesinin uyarlanmış halidir (bkz. paragraf 2.6):

Image

Bu proje, önceki projeye kıyasla yeni Primefaces etiketleri getirmiyor. Bu nedenle bu proje hakkında yorum yapmayacağız. Bu proje, belgenin web sitesinde okuyucuların erişimine sunulan örnekler listesinin bir parçasıdır.

5.9. Örnek: mv-pf-06: gezinme – oturum – istisna yönetimi

Bu proje, JSF2 [mv-jsf2-05] projesinin uyarlanmış halidir (bkz. paragraf 2.7):

Yine, bu örnekte yeni Primefaces etiketleri kullanılmamaktadır. Yalnızca yukarıda çerçeveli bağlantı tablosu hakkında yorum yapacağız:


<p:panelGrid columns="6">
  <p:commandLink value="1" action="form1?faces-redirect=true" ajax="false"/>
  <p:commandLink value="2" action="#{form.doAction2}" ajax="false"/>
  <p:commandLink value="3" action="form3?faces-redirect=true" ajax="false"/>
  <p:commandLink value="4" action="#{form.doAction4}" ajax="false"/>
  <p:commandLink value="#{msg['form.pagealeatoireLink']}" action="#{form.doAlea}" ajax="false"/>
  <p:commandLink value="#{msg['form.exceptionLink']}" action="#{form.throwException}" ajax="false"/>
</p:panelGrid>
  • Tüm bağlantılarda ajax=false özniteliği bulunmaktadır. Dolayısıyla sayfa normal şekilde yüklenmektedir;
  • 2. ve 4. satırlarda, yönlendirmenin nasıl yapıldığına dikkat edelim.

5.10. Örnek: mv-pf-07: girişlerin doğrulanması ve dönüştürülmesi

Bu proje, JSF2 ve [mv-jsf2-06] projelerinin uyarlanmış halidir (bkz. paragraf 2.8):

Image

Uygulama, <p:messages> etiketini de dahil olmak üzere iki yeni etiket ekler:


<p:messages globalOnly="true"/>

Image

ve <p:message> etiketi:


<p:inputText id="saisie1" value="#{form.saisie1}" styleClass="saisie"/>
<p:message for="saisie1" styleClass="error"/>

JSF'teki <h:message> etiketine kıyasla, PF'teki <p:message> etiketi aşağıdaki değişiklikleri beraberinde getirir:

  • hata mesajının görünümü farklıdır ([1]),
  • hatalı giriş alanı kırmızı bir çerçeve ile çevrilmiştir ([2]).

5.11. Örnek: mv-pf-08: bileşenlerin durum değişikliğiyle ilgili olaylar

Bu proje, JSF2 ve [mv-jsf2-07] projelerinin uyarlanmış halidir (bkz. paragraf 2.9):

Image

JSF projesi, listeners kavramını getirmiştir. listener'in Primefaces ile yönetimi farklı bir şekilde gerçekleştirilmiştir.

JSF ile:

1
2
3
4
5
6
7
         <!-- satır 1 -->
        <h:outputText value="#{msg['combo1.prompt']}"/>
        <h:selectOneMenu id="combo1" value="#{form.combo1}" immediate="true" onchange="submit();" valueChangeListener="#{form.combo1ChangeListener}" styleClass="combo">
          <f:selectItems value="#{form.combo1Items}"/>
        </h:selectOneMenu>
        <h:panelGroup></h:panelGroup>
<h:outputText value="#{form.combo1}"/>

Primefaces ile:

<h:outputText value="#{msg['combo1.prompt']}"/>
        <p:selectOneMenu id="combo1" value="#{form.combo1}" styleClass="combo">
          <f:selectItems value="#{form.combo1Items}"/>
          <p:ajax update=":formulaire:combo2"/>  
        </p:selectOneMenu>
        <h:panelGroup></h:panelGroup>
        <h:outputText value="#{form.combo1}"/>

        <h:outputText value="#{msg['combo2.prompt']}"/>
        <p:selectOneMenu id="combo2" value="#{form.combo2}" styleClass="combo">
          <f:selectItems value="#{form.combo2Items}"/>
        </p:selectOneMenu>
  • 2. satır: valueChangeListener özniteliği içermeyen <h:selectOneMenu> etiketi,
  • 4. satır: <p:ajax> etiketi, üst etiketi olan <h:selectOneMenu>'e bir AJAX davranışı ekler. Varsayılan olarak, combo1 listesinin "değer değişikliği" olayına tepki verir. Bu olay gerçekleştiğinde, etiketinin ait olduğu formun değerleri bir AJAX çağrısı ile sunucuya gönderilir. Böylece model güncellenir. Bu yeni model, combo2 ile tanımlanan açılır listeyi güncellemek için kullanılır (10. satır). 4. satırda, AJAX çağrısının şablondaki herhangi bir yöntemi çalıştırmadığına dikkat edilmelidir. Bu, burada gereksizdir. Amacımız, girilen değerlere göre şablonu POST ile değiştirmektir.

5.12. Örnek: mv-pf-09: yardımlı veri girişi

Bu proje, belirli veri türlerinin girilmesini kolaylaştıran Primefaces'e özgü giriş etiketleri sunar:

5.12.1. NetBeans projesi

NetBeans projesi şu şekildedir:

Projenin önemi şudur:

  • proje tarafından görüntülenen tek sayfa olan [index.html],
  • bu sayfanın [Form.java] şablonunda yatmaktadır.

5.12.2. Şablon

Form, aşağıdaki şablonla ilişkili dört giriş alanı içerir:


package forms;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.ManagedBean;

@ManagedBean
@SessionScoped
public class Form implements Serializable {

  private Date calendrier;
  private Integer slider = 100;
  private Integer spinner = 1;
  private String autocompleteValue;

  public Form() {
  }

  public List<String> autocomplete(String query) {
    ...
  }
   // alıcı ve ayarlayıcılar
...
}

Bu dört giriş, 14-17. satırlardaki alanlarla ilişkilidir.

5.12.3. Form

Form şu şekildedir:


<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">

  <ui:composition template="layout.xhtml">
    <ui:define name="contenu">
      <h2><h:outputText value="#{msg['app.titre']}"/></h2>
      <p:growl id="messages" autoUpdate="true"/>
      <p:panelGrid columns="3" columnClasses="col1,col2,col3,col4">
        <h:outputText value="#{msg['saisie.type']}" styleClass="entete"/>
        <h:outputText value="#{msg['saisie.champ']}" styleClass="entete"/>
        <h:outputText value="#{msg['bean.valeur']}" styleClass="entete"/>

        <!-- takvim -->
              ...

        <!-- kaydırma çubuğu -->
              ...

        <!-- döner simge -->
              ...

        <!-- otomatik tamamlama -->
              ...

      </p:panelGrid>
    </ui:define>
  </ui:composition>
</html>

Dört giriş alanını inceleyelim.

5.12.4. Takvim

<p:calendar> etiketi, takvimden bir tarih seçilmesini sağlar. Bu etiket çeşitli öznitelikleri destekler.


<h:outputText value="#{msg['calendar.prompt']}"/>
        <p:calendar id="calendrier" value="#{form.calendrier}" pattern="dd/MM/yyyy" timeZone="Europe/Paris"/>
        <h:outputText id="calendrierValue" value="#{form.calendrier}">
          <f:convertDateTime pattern="dd/MM/yyyy" type="date" timeZone="Europe/Paris"/>
        </h:outputText>

2. satırda, tarihin "gg/aa/yyyy" biçiminde görüntülenmesi ve saat diliminin Paris saat dilimi olması belirtilir. İmleci giriş alanına getirdiğinizde bir takvim görüntülenir:

 

5.12.5. Kaydırma çubuğu

<p:slider> etiketi, bir çubuk boyunca imleci kaydırarak bir tamsayı girilmesini sağlar:

 

Etiket kodu şöyledir:


        <h:outputText value="#{msg['slider.prompt']}"/>
        <h:panelGrid columns="1" style="margin-bottom:10px">  
          <p:inputText id="slider" value="#{form.slider}" required="true" requiredMessage="#{msg['slider.required']}" validatorMessage="#{msg['slider.invalide']}">  
            <f:validateLongRange minimum="100" maximum="200"/>
          </p:inputText>
          <p:slider for="slider" minValue="100" maxValue="200"/>  
        </h:panelGrid>  
<h:outputText id="sliderValue" value="#{form.slider}"/>
  • 3. satır: Burada, tamsayı girişi sağlayan klasik bir <p:inputText> etiketi bulunmaktadır. Bu değer, kaydırma çubuğu kullanılarak da girilebilir,
  • 4. satır: <p:slider> etiketi, <p:inputText> giriş etiketiyle ilişkilendirilmiştir (for özniteliği). Bu etikete bir minimum ve bir maksimum değer atanır.

5.12.6. Spinner

Bu bileşeni daha önce de tanıtmıştık:


        <h:outputText value="#{msg['spinner.prompt']}"/>
        <p:spinner id="spinner" min="1" max="12" value="#{form.spinner}" required="true" requiredMessage="#{msg['spinner.required']}" validatorMessage="#{msg['spinner.invalide']}">
          <f:validateLongRange minimum="1" maximum="12"/>
        </p:spinner>
<h:outputText id="spinnerValue" value="#{form.spinner}"/>

3. satırda, spinner 1 ile 12 arasında bir tamsayı girilmesine olanak tanır. Sayı, doğrudan spinner'ın giriş alanına girilebilir veya ok tuşları kullanılarak girilen sayı artırılıp azaltılabilir.

 

5.12.7. Yardımlı giriş

Giriş yardımı, girişin ilk karakterlerini yazmaktan ibarettir. Ardından bir açılır listede öneriler görünür. Bunlardan birini seçebilirsiniz. Bu bileşen, açılır listelerin içeriği çok fazla olduğunda, açılır listeler yerine kullanılır. Örneğin, Fransa'daki şehirlerin bir açılır listesini sunmak istediğimizi varsayalım. Bu, birkaç bin şehir demektir. Kullanıcının şehrin ilk üç harfini yazmasına izin verirsek, bu harflerle başlayan şehirlerin daha kısa bir listesini sunabiliriz.

 

Bu bileşenin kodu şöyledir:


        <h:outputText value="#{msg['autocomplete.prompt']}"/>
        <p:autoComplete value="#{form.autocompleteValue}" completeMethod="#{form.autocomplete}" required="true" requiredMessage="#{msg['autocomplete.required']}"/>
        <h:outputText id="autocompleteValue" value="#{form.autocompleteValue}"/>
        <h:panelGroup/>
        <h:panelGroup>
        <center><p:commandLink value="#{msg['valider']}" update="formulaire:contenu"/></center>
        </h:panelGroup>
<h:panelGroup/>

2. satırdaki <p:autoComplete> etiketi, otomatik tamamlama özelliğini sağlayan etikettir. Burada ilgilendiğimiz parametre, değeri kullanıcının girdiği karakterlere uygun önerilerde bulunmaktan sorumlu olan modelin bir yönteminin adı olan completeMethod özniteliğidir. Bu yöntem şöyledir:


  public List<String> autocomplete(String query) {
    List<String> results = new ArrayList<String>();

    for (int i = 0; i < 10; i++) {
      results.add(query + i);
    }

    return results;
}

  • 1. satır: Yöntem, kullanıcı tarafından giriş alanına yazılan karakter dizisini parametre olarak alır. Bir öneri listesi döndürür,
  • 4-6. satırlar: Parametre olarak alınan karakterleri içeren ve bunlara 0 ile 9 arasında bir rakam ekleyen 10 öneriden oluşan bir liste oluşturulur.

5.12.8. <p:growl> etiketi

<p:growl> etiketi, formun hata mesajlarını görüntüleyen <p:messages> etiketinin yerine kullanılabilir.


      <p:growl id="messages" autoUpdate="true"/>

Yukarıda id özniteliği kullanılmamıştır. autoUpdate=true özniteliği, hata mesajları listesinin formun her POST'unda yenilenmesi gerektiğini belirtir.

Aşağıdaki [1] formunu gönderdiğimizi varsayalım:

  • [2]'te, <p:growl> etiketi hatalı girdilerle ilişkili hata mesajlarını görüntüler.

5.13. Örnek: mv-pf-10: dataTable - 1

Bu proje, veri listelerini görüntülemek için kullanılan <p:dataTable> etiketini sunar

Image

5.13.1. NetBeans projesi

NetBeans projesi şu şekildedir:

Projenin önemi şudur:

  • proje tarafından görüntülenen tek sayfa olan [index.html],
  • bu sayfanın [Form.java] şablonu ve [Personne] bean'i.

5.13.2. Mesaj dosyası

[messages_fr.properties] dosyası şöyledir:


app.titre=intro-08
app.titre2=DataTable - 1
submit=Valider
personnes.headers.id=Id
personnes.headers.nom=Nom
personnes.headers.prenom=Pr\u00e9nom
layout.hautdepage=Primefaces en fran\u00e7ais
layout.menu=Menu fran\u00e7ais
layout.basdepage=ISTIA, universit\u00e9 d'Angers
form.langue1=Fran\u00e7ais
form.langue2=Anglais
form.noData=La liste des personnes est vide
form.listePersonnes=Liste de personnes
form.action=Action

5.13.3. Şablon

[Personne] bean'i bir kişiyi temsil eder:


package forms;

import java.io.Serializable;

public class Personne implements Serializable{
  // veri
  private int id;
  private String nom;
  private String prénom;
  
  // yapıcılar
  public Personne(){
    
  }
  
  public Personne(int id, String nom, String prénom){
    this.id=id;
    this.nom=nom;
    this.prénom=prénom;
  }
  
  // toString
  public String toString(){
    return String.format("Personne[%d,%s,%s]", id,nom,prénom);
  }
  
  // getter ve setter'lar
...
}

[index.xhtml] sayfa şablonu, aşağıdaki [Form] sınıfına aittir:


package forms;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class Form implements Serializable{

  // model
  private List<Personne> personnes;
  private int personneId;

  // oluşturucu
  public Form() {
    // kişi listesinin başlatılması
    personnes = new ArrayList<Personne>();
    personnes.add(new Personne(1, "dupont", "jacques"));
    personnes.add(new Personne(2, "durand", "élise"));
    personnes.add(new Personne(3, "martin", "jacqueline"));
  }

  public void retirerPersonne() {
...
  }
  
  // getter ve setter'lar
...  
}
  • 9-10. satırlar: bean, oturum kapsamındadır,
  • 18-24. satırlar: Oluşturucu, üç kişiden oluşan bir liste oluşturur; bu liste, istekler boyunca varlığını sürdürecektir,
  • 15. satır: listeden silinecek bir kişinin numarası,
  • 26-28. satırlar: silme yöntemi.

5.13.4. Form

Form şu şekildedir: [index.xhtml]:


<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
  <ui:composition template="layout.xhtml">
    <ui:define name="contenu">
      <h2><h:outputText value="#{msg['app.titre2']}"/></h2>
      <p:dataTable value="#{form.personnes}" var="personne" emptyMessage="#{msg['form.noData']}">
        <f:facet name="header">  
           #{msg['form.listePersonnes']}  
        </f:facet>  
        <p:column>
          <f:facet name="header">
             #{msg['personnes.headers.id']}
          </f:facet>
           #{personne.id}
        </p:column>
        <p:column>
          <f:facet name="header">
             #{msg['personnes.headers.nom']}
          </f:facet>
           #{personne.nom}
        </p:column>
        <p:column>
          <f:facet name="header">
             #{msg['personnes.headers.prenom']}
          </f:facet>
           #{personne.prénom}
        </p:column>
        <p:column>
          <f:facet name="header">
             #{msg['form.action']}
          </f:facet>
          <p:commandLink value="Retirer" action="#{form.retirerPersonne}" update=":formulaire:contenu">
            <f:setPropertyActionListener target="#{form.personneId}" value="#{personne.id}"/>
          </p:commandLink>
        </p:column>
      </p:dataTable>
    </ui:define>
  </ui:composition>
</html>

Bu, aşağıdaki görünümü oluşturur (aşağıdaki kutucuk):

  • 12. satır: Yukarıda çerçeveli tabloyu oluşturur. value özniteliği, tablo tarafından görüntülenen koleksiyonu belirtir; burada modeldeki kişilerin listesi. emptyMessage özniteliği isteğe bağlıdır. Liste boş olduğunda görüntülenecek mesajı belirtir. Varsayılan olarak 'no records found'dır. Burada ise şöyle olacaktır:
 
  • 13-15. satırlar: [1] başlığını oluşturur,
  • satır 16-21: [2] sütununu oluşturur,
  • 22-27. satırlar: [3] sütununu oluşturur,
  • 28-33. satırlar: [4] sütununu oluşturur,
  • 34-41. satırlar: [5] sütununu oluşturur.

[Retirer] bağlantısı, bir kişiyi listeden çıkarmaya yarar. [38] satırı; bu işlemi gerçekleştiren yöntem [Form].retirerPersonne'tir. Bu yöntem, listeden çıkarılacak kişinin numarasını bilmelidir. Bu numara 39. satırda verilmektedir. 38. satırda action özniteliği kullanılmıştır. Diğer durumlarda ise actionListener özniteliği kullanılmıştır. Bu iki özniteliğin işlevsel farkını tam olarak anladığımdan emin değilim. Ancak uygulamada, <setPropertyActionListener> etiketleriyle belirlenen özniteliklerin, action özniteliğiyle belirtilen yöntemin yürütülmesinden önce ayarlandığı, actionListener özniteliği için ise durumun böyle olmadığı görülmektedir. Basitçe söylemek gerekirse, çağrılan eyleme gönderilecek parametreler olduğunda action özniteliğini kullanmak gerekir.

Bir kişiyi listeden kaldırma yöntemi şöyledir:


...
@ManagedBean
@SessionScoped
public class Form implements Serializable{

  // örnek
  private List<Personne> personnes;
  private int personneId;

  public void retirerPersonne() {
    // seçilen kişi aranıyor
    int i = 0;
    for (Personne personne : personnes) {
      // seçili kişi = mevcut kişi mi?
      if (personne.getId() == personneId) {
        // listeden mevcut kişiyi siliyoruz
        personnes.remove(i);
        // işlem tamamlandı
        break;
      } else {
        // sonraki kişi
        i++;
      }
    }
  }
...  
}

5.14. Örnek: mv-pf-11: dataTable - 2

Bu proje, bir satırın seçilebileceği bir veri listesini gösteren bir tablo sunmaktadır:

Tablodan bir satır seçildiğinde, POST anında seçilen satırla ilgili bilgiler modele gönderilir. Böylece, kişi başına bir [Retirer] bağlantısına gerek kalmaz. Tablonun tamamı için tek bir bağlantı yeterlidir.

NetBeans projesi, birkaç ayrıntı dışında öncekiyle aynıdır: form ve şablonu. [index.xhtml] formu şöyledir:


<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
  <ui:composition template="layout.xhtml">
    <ui:define name="contenu">
      <h2><h:outputText value="#{msg['app.titre2']}"/></h2>
      <p:dataTable value="#{form.personnes}" var="personne" emptyMessage="#{msg['form.noData']}"
                   rowKey="#{personne.id}"  selection="#{form.personneChoisie}" selectionMode="single">
        ...
      </p:dataTable>
      <p:commandLink value="Retirer" action="#{form.retirerPersonne}" update=":formulaire:contenu"/>
    </ui:define>
  </ui:composition>
</html>
  • 13. satır: selectionMode özniteliği, single veya multiple seçim modlarından birini seçmeye olanak tanır. Burada, yalnızca tek bir satırı seçmeyi tercih ettik,
  • 13. satır: rowkey özniteliği, görüntülenen öğeleri benzersiz bir şekilde seçmeyi sağlayan bir özniteliği belirtir. Burada, seçilen kişinin kimliğini seçtik,
  • 13. satır: selection özniteliği, seçilen kişiye ait bir referans alacak olan model özniteliğini belirtir. Önceki rowkey özniteliği sayesinde, sunucu tarafında seçilen kişiye ait bir referans hesaplanabilecektir. Kullanılan yöntemin ayrıntıları elimizde yok. Koleksiyonun, seçilen rowkey’e karşılık gelen öğeyi bulmak için sırayla taranıyor olabileceğini tahmin edebiliriz. Bu, rowkey’i selection ile ilişkilendiren yöntem daha karmaşıksa, bu yöntemin kullanılamayacağı anlamına gelir,

Bunu açıklığa kavuşturduktan sonra, [Form].retirerPersonne yöntemi şu şekilde değiştirilir:


...

@ManagedBean
@SessionScoped
public class Form implements Serializable {

  // şablon
  private List<Personne> personnes;
  private Personne personneChoisie;

  // üretici
  public Form() {
  ...
  }

  public void retirerPersonne() {
    // seçilen kişi kaldırılır
    personnes.remove(personneChoisie);
  }

  // getter ve setter'lar
...
}
  • 9. satır: Her POST çağrısında, 9. satırdaki referans, 8. satırdaki listede yer alan seçilen kişinin referansı ile başlatılır,
  • 18. satırda: kişinin silinmesi bu sayede basitleştirilir. Önceki örnekte yaptığımız arama, <dataTable> etiketiyle gerçekleştirilmiştir.

5.15. Örnek: mv-pf-12: dataTable - 3

Bu proje bir öncekine benzerdir. Özellikle görünüm tamamen aynıdır:

Image

NetBeans projesi, birazdan inceleyeceğimiz birkaç ayrıntı dışında öncekiyle aynıdır. [index.xhtml] formu şu şekilde değişir:


...
  <ui:composition template="layout.xhtml">
    <ui:define name="contenu">
      <h2><h:outputText value="#{msg['app.titre2']}"/></h2>
      <p:dataTable value="#{form.personnes}" var="personne" emptyMessage="#{msg['form.noData']}"
                   selectionMode="single" selection="#{form.personneChoisie}">
  ...
      </p:dataTable>
      <p:commandLink value="Retirer" action="#{form.retirerPersonne}" update=":formulaire:contenu"/>
    </ui:define>
  </ui:composition>
</html>
  • 6. satırda, rowkey özniteliği kaldırılmış, selection özniteliği ise kalmıştır. rowkey ve selection öznitelikleri arasındaki bağlantı artık bir sınıf aracılığıyla sağlanmaktadır. 5. satırdaki value özniteliğinin değeri artık Primefaces SelectableDataModel<T> arayüzünün bir örneğidir. Modelin [Form].getPersonnes yöntemi şu şekilde değişmiştir:

  public DataTableModel getPersonnes() {
    return new DataTableModel(personnes);
}

Böylece projeye yeni bir bean eklenir:

Bu bean şöyledir:


package forms;

import java.util.List;
import javax.faces.model.ListDataModel;
import org.primefaces.model.SelectableDataModel;

public class DataTableModel extends ListDataModel<Personne> implements SelectableDataModel<Personne> {

  // yapıcılar
  public DataTableModel() {
  }

  public DataTableModel(List<Personne> personnes) {
    super(personnes);
  }

  @Override
  public Object getRowKey(Personne personne) {
    return personne.getId();
  }

  @Override
  public Personne getRowData(String rowKey) {
    // kişi listesi
    List<Personne> personnes = (List<Personne>) getWrappedData();
    // anahtar bir tamsayıdır 
    int key = Integer.parseInt(rowKey);
    // seçilen kişiyi arıyoruz
    for (Personne personne : personnes) {
      if (personne.getId() == key) {
        return personne;
      }
    }
    // hiçbir şey bulunamadı
    return null;
  }
}
  • 7. satır: Sınıf, SelectableDataModel arayüzünün bir örneğidir. Bu arayüzü en az iki sınıf uygulamaktadır: oluşturucusu parametre olarak bir liste kabul eden ListDataModel ve oluşturucusu parametre olarak bir dizi kabul eden ArrayDataModel. Burada, bean'imiz ListDataModel sınıfını genişletmektedir,
  • 13-15. satırlar: Oluşturucu, yönettiğimiz kişilerin listesini parametre olarak kabul eder. Bu parametre üst sınıfa aktarılır,
  • 18. satır: getRowKey yöntemi, kaldırılan rowkey özniteliğinin rolünü üstlenir. Bir kişiyi benzersiz bir şekilde tanımlamaya yarayan nesneyi, burada kişinin kimliğini döndürmelidir,
  • 23. satır: getRowData yöntemi, rowkey'i kullanarak seçilen nesneyi döndürmelidir. Yani burada, bir kişiyi kimliğine göre döndürmelidir. Bu şekilde elde edilen referans, dataTable etiketindeki selection özniteliğinin hedef nesnesine atanacaktır; burada selection="#{form.personneChoisie}" özniteliği söz konusudur. Yöntemin parametresi, kullanıcı tarafından seçilen nesnenin rowkey'idir ve bir karakter dizisi biçimindedir,
  • 24-35. satırlar: Kimliği alınan kişiye ait referansı verir. Bu referans, [Form].personneChoisie şablonuna atanacaktır. Dolayısıyla [retirerPersonne] yöntemi değişmeden kalır:

  public void retirerPersonne() {
    // seçilen kişi listeden kaldırılıyor
    personnes.remove(personneChoisie);
  }

rowkey ve selection öznitelikleri arasındaki bağlantı, basit bir özellik (rowkey) ile nesne (selection) bağlantısı olmadığında bu teknik kullanılmalıdır.

5.16. Örnek: mv-pf-13: dataTable - 4

Bu proje, çıkarılacak kişinin seçim şekli dışında bir önceki projeye benzerdir:

Image

Yukarıda, nesnenin bir bağlam menüsü (sağ tıklama) aracılığıyla seçildiğini görüyoruz. Silme işlemi için onay isteniyor:

 

[index.xhtml] formu şu şekilde değişir:


...
  <ui:composition template="layout.xhtml">
    <ui:define name="contenu">

      <!-- başlık -->
      <h2><h:outputText value="#{msg['app.titre2']}"/></h2>

      <!-- bağlam menüsü -->
      <p:contextMenu for="personnes">  
        <p:menuitem value="#{msg['form.supprimer']}" onclick="confirmation.show()"/>
      </p:contextMenu>  

      <!-- iletişim kutusu -->
      <p:confirmDialog widgetVar="confirmation" message="#{msg['form.suppression.confirmation']}"  
                       header="#{msg['form.suppression.message']}" severity="alert" >                   
        <p:commandButton value="#{msg['form.supprimer.oui']}" update=":formulaire:contenu"                          action="#{form.retirerPersonne}" oncomplete="confirmation.hide()"/>
        <p:commandButton value="#{msg['form.supprimer.non']}" onclick="confirmation.hide()" type="button" />                
      </p:confirmDialog>  

      <!-- dataTable-->
      <p:dataTable id="personnes" value="#{form.personnes}" var="personne" emptyMessage="#{msg['form.noData']}"
                   selection="#{form.personneChoisie}" selectionMode="single">
        ...
      </p:dataTable>
    </ui:define>
  </ui:composition>
</html>
  • 9-11. satırlar: 21. satırdaki (id özniteliği) dataTable için bir bağlam menüsü tanımlar (for özniteliği). Dolayısıyla, bu bağlam menüsü, kişi tablosuna sağ tıklama yapıldığında görünür,
  • 10. satır: Menümüzde tek bir seçenek bulunmaktadır (menuItem etiketi). Bu seçeneğe tıklandığında, onclick özniteliğindeki JavaScript kodu çalıştırılır. [confirmation.show()] JavaScript kodu, 14. satırdaki (widgetVar özniteliği) iletişim kutusunu görüntüler. Bu iletişim kutusu şöyledir:
  • 14. satır: message özniteliği [3]'i, header özniteliği [1]'i, severity özniteliği ise [2] simgesini görüntüler,
  • 16. satır: [4] değerini görüntüler. Tıklandığında kişi silinir (action özniteliği), ardından iletişim kutusu kapatılır (oncomplete özniteliği). oncomplete özniteliği, sunucu tarafındaki işlem tamamlandıktan sonra yürütülen JavaScript kodudur,
  • 17. satır: [5] mesajını görüntüler. Tıklandığında, iletişim kutusu kapatılır ve kişi silinmez.

5.17. Örnek: mv-pf-14: dataTable - 5

Bu proje, AJAX çağrısının yürütülmesinden sonra sunucudan geri dönüş alınabileceğini göstermektedir. Bunun için AJAX çağrısının oncomplete özniteliği kullanılır:

 

[index.xhtml] formu şu şekilde değişir:


...
  <ui:composition template="layout.xhtml">
    <ui:define name="contenu">
...
<!-- iletişim kutusu 1 -->
      <p:confirmDialog widgetVar="confirmation" ... >                   
        <p:commandButton value="#{msg['form.supprimer.oui']}" update=":formulaire:contenu" action="#{form.retirerPersonne}" oncomplete="handleRequest(xhr, status, args);confirmation.hide()"/>
        <p:commandButton ... />                
      </p:confirmDialog>  

      <!-- Javascript -->
      <script type="text/javascript">  
        function handleRequest(xhr, status, args) {  
          // hata mı?
          if(args.msgErreur) {  
            alert(args.msgErreur);  
          }  
        }  
      </script> 
...
      </p:dataTable>
    </ui:define>
  </ui:composition>
</html>
  • 7. satır: oncomplete özniteliği, 13-18. satırlardaki JavaScript işlevini çağırır,
  • 13. satır: Yöntemin imzası bu şekilde olmalıdır. args, sunucu tarafındaki modelin zenginleştirebileceği bir sözlüktür,
  • 15. satır: args sözlüğünde 'msgErreur' adlı bir öznitelik olup olmadığına bakılır. Varsa, görüntülenir (16. satır).

Modelde, [retirerPersonne] yöntemi şu şekilde gelişir:


public void retirerPersonne() {
    // rastgele silme
    int i = (int) (Math.random() * 2);
    if (i == 0) {
      // seçilen kişi kaldırılır
      personnes.remove(personneChoisie);
    } else {
      // hata mesajı gönderiliyor
      String msgErreur = Messages.getMessage(null, "form.msgErreur", null).getSummary();
      RequestContext.getCurrentInstance().addCallbackParam("msgErreur", msgErreur);
    }
  }
  • 3. satır: 0 veya 1 arasında rastgele bir sayı çekilir,
  • 4-6. satırlar: 0 ise, kullanıcı tarafından seçilen kişi kişi listesinden silinir,
  • 9. satır: aksi takdirde, uluslararası bir hata mesajı oluşturulur:

form.msgErreur=La personne n'a pu \u00eatre supprim\u00e9e. Veuillez r\u00e9essayer ult\u00e9rieurement.
form.msgErreur_detail=La personne n'a pu \u00eatre supprim\u00e9e. Veuillez r\u00e9essayer ult\u00e9rieurement.
  • 10. satır: Bahsettiğimiz args sözlüğüne, 9. satırda oluşturulan msgErreur değerine sahip 'msgErreur' adlı özniteliği eklemeyi amaçlayan karmaşık bir komut. Bu öznitelik daha sonra [index.xhtml] adlı JavaScript yöntemi tarafından alınır:

      <!-- Javascript -->
      <script type="text/javascript">  
        function handleRequest(xhr, status, args) {  
          // hata mı?
          if(args.msgErreur) {  
            alert(args.msgErreur);  
          }  
        }  
</script> 

5.18. Örnek: mv-pf-15: araç çubuğu

Bu projede bir araç çubuğu oluşturuyoruz:

Araç çubuğu, yukarıda çerçeveli olarak gösterilen bileşendir. Aşağıdaki XHTML kodu ile elde edilir: [index.xhtml]:



<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
  <ui:composition template="layout.xhtml">
    <ui:define name="contenu">
      <!-- başlık -->
      <h2><h:outputText value="#{msg['app.titre2']}"/></h2>

      <!-- araç çubuğu-->
      <p:toolbar>
        <p:toolbarGroup align="left">  
          ...  
        </p:toolbarGroup>
        <p:toolbarGroup align="right">  
          ...  
        </p:toolbarGroup>  
      </p:toolbar>
    </ui:define>
  </ui:composition>
</html>
  • 15-22. satırlar: araç çubuğu,
  • 16-18. satırlar: çubuğun solundaki bileşen grubunu tanımlar,
  • 19-21. satırlar: sağdaki bileşenler için de aynısı geçerlidir.

Araç çubuğunun solundaki bileşenler şunlardır:


        <p:toolbarGroup align="left">  
          <h:outputText value="#{msg['form.etudiant']}"/>
          <p:spacer width="50px"/>
          <p:selectOneMenu value="#{form.personneId}" effect="fade">  
            <f:selectItems value="#{form.personnes}" var="personne" itemLabel="#{personne.prénom} #{personne.nom}" itemValue="#{personne.id}"/>  
          </p:selectOneMenu>              
          <p:separator/>
          <p:commandButton id="delete-personne" icon="ui-icon-trash" action="#{form.supprimerPersonne}" update=":formulaire:contenu"/>  
          <p:tooltip for="delete-personne" value="#{msg['form.delete.personne']}"/>  
</p:toolbarGroup>

Aşağıdaki görünümü gösterirler:

  • 2. satır: [1]'i görüntüler,
  • 3. satır: 30 piksel boşluk gösterir [2],
  • 4-6. satırlar: bir kişi listesi içeren açılır menü görüntüler ([3]),
  • 7. satır: bir ayırıcı görüntüler [4],
  • 8. satır: açılır listeden seçilen kişiyi silmekle görevli bir düğme görüntüler. Düğmenin bir simgesi vardır. Bu simgeler şunlardır: JQuery UI. Bu simgelerin listesi URL, [http://jqueryui.com/themeroller/] ve [6]'te bulunur:
  • Bir simgenin adını öğrenmek için fareyi simgenin üzerine getirmeniz yeterlidir. Ardından bu ad, <commandButton> bileşeninin icon özniteliğinde kullanılır; örneğin, icon="ui-icon-trash". Yukarıda verilen adın .ui-icon-trash olduğu ve icon, özniteliğinde bu adın başındaki noktanın kaldırıldığına dikkat edilmelidir
  • 9. satır: Düğme için bir yardım balonu oluşturur (for özniteliği). İmleci düğmenin üzerinde tuttuğunuzda, [7] yardım mesajı görüntülenir.

Bu bileşenlerle ilişkili şablon şöyledir:


package forms;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class Form implements Serializable {

  // şablon
  private List<Personne> personnes;
  private int personneId;

  // üretici
  public Form() {
    // kişi listesinin başlatılması
    personnes = new ArrayList<Personne>();
    personnes.add(new Personne(1, "dupont", "jacques"));
    personnes.add(new Personne(2, "durand", "élise"));
    personnes.add(new Personne(3, "martin", "jacqueline"));
  }

  public void supprimerPersonne() {
    // seçilen kişi aranıyor
    int i = 0;
    for (Personne personne : personnes) {
      // seçili kişi = mevcut kişi mi?
      if (personne.getId() == personneId) {
        // listeden mevcut kişiyi siliyoruz
        personnes.remove(i);
        // işlem tamamlandı
        break;
      } else {
        // sonraki kişi
        i++;
      }
    }
  }

  // alıcı ve ayarlayıcılar
  ...
}

Araç çubuğunun sağındaki bileşenler şunlardır:


<p:toolbar>
        <p:toolbarGroup align="left">  
          ... 
        </p:toolbarGroup>
        <p:toolbarGroup align="right">  
          <p:menuButton value="#{msg['form.options']}">  
            <p:menuitem id="menuitem-francais" value="#{msg['form.francais']}" actionListener="#{changeLocale.setFrenchLocale}" update=":formulaire"/>  
            <p:menuitem id="menuitem-anglais" value="#{msg['form.anglais']}" actionListener="#{changeLocale.setEnglishLocale}" update=":formulaire"/>  
          </p:menuButton>  
        </p:toolbarGroup>  
      </p:toolbar>

Aşağıdaki görünümü gösterirler:

 
  • 6-9. satırlar: bir menü düğmesi. Menü seçeneklerini içerir,
  • 7. satır: Formu Fransızca'ya çevirme seçeneği,
  • 8. satır: Formu İngilizceye çevirme seçeneği.

5.19. Conclusion

Örnek uygulamamızı Primefaces'e taşımak için yeterli bilgiye sahibiz. Kütüphanede 100'den fazla bileşen bulunmasına rağmen, biz sadece on beş kadarını inceledik. Okuyucunun, eksik bulduğu bileşeni doğrudan Primefaces sitesinde araması önerilir.

5.20. Eclipse ile testler

Maven projeleri, [1] örnekleri web sitesinde mevcuttur:

Eclipse'e aktarıldıktan sonra, [2] ile çalıştırılabilirler. [3]'te Tomcat seçilir. Ardından, Eclipse'in dahili tarayıcısında [3] olarak görüntülenirler.