Salut à tous,
j'aimerais connaitre la meilleur facon de créer nos propres composants ainsi de faire une template en jsf(j'ai entendu parler de facelets,pas trop compris le systéme,si vous connaissez un site si possible en fr,ca serait sympa)
Salut à tous,
j'aimerais connaitre la meilleur facon de créer nos propres composants ainsi de faire une template en jsf(j'ai entendu parler de facelets,pas trop compris le systéme,si vous connaissez un site si possible en fr,ca serait sympa)
Bonjour,
Il faudrait en savoir un peu plus sur le genre de composant que tu veux créer.
En gros, il y a deux voies :
1. Tu utilises les Facelets. Il s'agit là de faire un composant représentant une composition (un ensemble) de composants déjà existants. C'est rapide, simple, mais limité : par exemple, il n'est pas forcément possible d'affecter un ID à un composant de ce type.
Voici un composant fait à partir de composition qui permet de gérer facilement une colonne d'une DataTable (avec des liens permettant de trier la colonne en question) :
(j'ai un peu simplifié le code, voir la page ici pour plus de détails).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 <!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" ...> <ui:composition> <h:column> <f:facet name="header"> <h:panelGroup> ${label} [ <!-- Sort ascending --> <h:commandLink styleClass="smallLink" action="#{backingBean.sort}"> <h:outputText value="asc" /> <f:param name="by" value="${fieldName}"/> <f:param name="order" value="asc"/> </h:commandLink> , <!-- Sort descending --> <h:commandLink styleClass="smallLink" action="#{backingBean.sort}"> <h:outputText value="asc" /> <f:param name="by" value="${fieldName}"/> <f:param name="order" value="dec"/> </h:commandLink> ] </h:panelGroup> </f:facet> <!-- Display the field name --> <h:outputText value="${entity[fieldName]}"/> </h:column> </ui:composition> </html>
2. La seconde voie est de créer un composant en les codant en Java. Là, c'est plus complexe (il faut créer une classe pour le Renderer, une classe pour l'objet JSF, etc.) mais ça permet de créer absolument tout ce que l'on veut.
De mon côté, sur mon projet, nous utilisons les 2 méthodes. Quant la composition est possible, on l'utilise, sinon on crée nos propres composants. En fait, pour être plus précis, nous créons des composants en étendant des composants déjà existants.
Par exemple, nous avions besoin de créer un composant de type AjaxButton (a4j:commandButton), nous avons donc créer notre composant (qui étend la classe org.ajax4jsf.ajax.html.HtmlAjaxCommandButton), ainsi que le composant graphique (étandant la classe org.ajax4jsf.renderkit.html.CommandButtonRenderer).
J'espère t'avoir mis sur la bonne voie...
Nous sommes tous semblables, alors acceptons nos différences !
--------------------------------------------------------------
Liens : Blog | Page DVP | Twitter
Articles : Hudson | Sonar | Outils de builds Java Maven 3 | Play! 1 | TeamCity| CitConf 2009
Critiques : Apache Maven
merci pour ta réponse
Ceux que j'ai compris par rapport à ton exemple,c'est qu'une variable contient le code permettant dans ton cas de trier une datable
Et si par exemple,j'ai envi de créer des composants dynamiques à partir d'un fichier xml.Je m'explique,j'ai un fichier qui contient des informations(faut voir sous qu'elle forme)et à partir de ses données,nous pouvons créer par exemple une datatable,un champ texte...,en fait des composant dynamique.
Aurais tu un petit exemple pour avoir un appercu d'un composant créer totalement
De rien
Tu parles de quoi au juste ? De ça : action="#{backingBean.sort}" ?
Ce bout de code signifie juste que lorsque l'utilisateur clique sur le lien, alors c'est la méthode sort du bean backingBean qui sera exécutée.
Il s'agit juste d'une expression EL.
Le principe général d'une composition, c'est d'externaliser un ensemble (une composition) de composants déjà existants, et ensuite de les appeler dans d'autres pages. Par exemple, l'exemple donné sera appelé juste par :
Hum, c'est bizarre comme idée. Pourquoi faire cela ? J'ai un peu de mal à comprendre pourquoi par moment tu devrais afficher un datatable, d'autre fois un champ texte... Pourquoi ne pas faire des sous-pages qui seront affichées ou non selon certaines conditions.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 ... <myns:myColumnComponent label="Item description" fieldName="description" entity="#{myBean}"/> ...
Tu peux jouer avec l'attribut rendered pour t'aider. Un exemple:
Ce code dit ceci : Si l'attribut readOnly (getter isReadOnly du bean myBean) vaut true, alors c'est le composant outputText qui sera affiché. S'il faut false, alors ce sera le composant inputText qui sera affiché. Mais jamais les deux en même temps.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 ... <h:inputText value="" ... rendered="#{!myBean.isReadOnly}"/> <h:outputText value="#{myBean.value}" ... rendered="#{myBean.isReadOnly}"/> ...
Voici un exemple de composant créé en Java. En fait, de mon côté, je ne fais qu'étendre un composant qui existe déjà. Ca me facilite la tâche. Et généralement, les composants dont j'ai besoin ne sont que des composants déjà existants, mais avec un certain nombre de nouvelles fonctionnalités, ou alors avec un rendu différent.
Mon exemple ici c'est la possibilité de créer un bouton avec des bords arrondis . Du coup, j'étends le <h:commandButton>, mais je change un peu son rendu, pour construire un petit tableau dans lequel je mettrais mes images pour créer le rendu du bouton.
Voici l'objet Java:
La classe qui se charge de son rendu:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 package mypackage.component; import javax.faces.component.html.HtmlCommandButton; import javax.faces.context.FacesContext; import javax.faces.el.ValueBinding; public class MyHtmlButton extends HtmlCommandButton { private String buttonType; public String getButtonType() { if (buttonType != null) { return buttonType; } ValueBinding vb = getValueBinding("buttonType"); if (vb != null) { return (String) vb.getValue(getFacesContext()); } return null; } public void setButtonType(String buttonType) { this.buttonType = buttonType; } @Override public void restoreState(FacesContext context, Object state) { Object values[] = (Object[]) (Object[]) state; super.restoreState(context, values[0]); buttonType = (String) values[1]; } @Override public Object saveState(FacesContext context) { Object[] values = new Object[2]; values[0] = super.saveState(context); values[1] = buttonType; return (Object) values; } }
Ensuite, je me créé un fichier taglib (romain.taglib.xml) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
59
60
61 package mypackage.renderkit; import java.io.IOException; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import mypackage.MyComponentUtils; import com.sun.faces.renderkit.html_basic.ButtonRenderer; public class MyButtonRenderer extends ButtonRenderer { public OpmButtonRenderer() { super(); } @Override public void encodeBegin(FacesContext context, UIComponent component) throws IOException { ResponseWriter writer = context.getResponseWriter(); String buttonType = getButtonType(component); writer.startElement("table", null); writer.writeAttribute("border", "0", "table"); writer.writeAttribute("cellpadding", "0", "table"); writer.writeAttribute("cellspacing", "0", "table"); writer.startElement("tr", null); writer.startElement("td", null); writer.startElement("img", null); writer.writeAttribute("src", MyComponentUtils.getResourceUrl("images/button_" + buttonType + "_left.gif"), "img"); writer.endElement("img"); writer.endElement("td"); writer.startElement("td", null); component.getAttributes().put("styleClass", buttonType + "Button"); super.encodeBegin(context, component); } @Override public void encodeEnd(FacesContext context, UIComponent component) throws IOException { super.encodeEnd(context, component); ResponseWriter writer = context.getResponseWriter(); writer.endElement("td"); writer.startElement("td", null); writer.startElement("img", null); writer.writeAttribute("src", MyComponentUtils.getResourceUrl("images/button_" + getButtonType(component) + "_right.gif"), "img"); writer.endElement("img"); writer.endElement("td"); writer.endElement("tr"); writer.endElement("table"); } private String getButtonType(UIComponent component) { String type = (String) component.getAttributes().get("buttonType"); if ((type != null) && (type.equalsIgnoreCase("std") || type.equalsIgnoreCase("default"))) { return type.toLowerCase(); } return MyComponentUtils.DEFAULT_BUTTON_CSS_CLASS; } }
Je "lie" ces types aux classes Java dans le fichier faces-config.xml:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12<facelet-taglib> <namespace>http://romain/jsf</namespace> ... <tag> <tag-name>button</tag-name> <component> <component-type>my.component.button</component-type> <renderer-type>my.renderkit.button</renderer-type> </component> </tag> </facelet-taglib>
Maintenant, quand je veux appeler ce composant dans une page, je fais :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 <faces-config> ... <component> <component-type>my.component.button</component-type> <component-class>mypackage.MyHtmlButton</component-class> </component> <render-kit> <render-kit-id>HTML_BASIC</render-kit-id> <renderer> <component-family>javax.faces.Command</component-family> <renderer-type>my.renderkit.button</renderer-type> <renderer-class>mypackage.MyButtonRenderer</renderer-class> </renderer> </render-kit> </faces-config>
J'espère être clair :o)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 <a4j:page xmlns="http://www.w3.org/1999/xhtml" ... xmlns:romain="http://romain/jsf"> ... <romain:button .../> ... </a4j:page>
Nous sommes tous semblables, alors acceptons nos différences !
--------------------------------------------------------------
Liens : Blog | Page DVP | Twitter
Articles : Hudson | Sonar | Outils de builds Java Maven 3 | Play! 1 | TeamCity| CitConf 2009
Critiques : Apache Maven
niquel
Lors de l'appel de ce composant,je ne vois pas trop les tags à mettre et que rajouter à la pace des ...
Dans mon cas, j'ai étendu le composant <h:commandButton/>.
J'ai donc à ma disposition toute la liste des attributs de ce composant. Tu peux les voir ici.
J'ai également ajouté à mon composant un attribut "buttonType", qui me permet en fait de définir la classe CSS qui sera utilisée pour le bouton.
Nous sommes tous semblables, alors acceptons nos différences !
--------------------------------------------------------------
Liens : Blog | Page DVP | Twitter
Articles : Hudson | Sonar | Outils de builds Java Maven 3 | Play! 1 | TeamCity| CitConf 2009
Critiques : Apache Maven
'essaye de reproduire ton exemple,lors du fichier MyButtonRendered,il me manque le fichier MyComponentUtils
Oui, en effet. Il s'agit juste d'une classe d'utilitaires, dont voici le code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 package mypackage; import javax.el.ValueExpression; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; public final class MyComponentUtils { private OpmComponentUtils() { } public static final String DEFAULT_BUTTON_CSS_CLASS = "std"; /** * Returns the complete Url of a resource handled by the Weblet framework. * * @param resource The resource we are looking for. * @return The complete Url of the resource. */ public static String getResourceUrl(String resource) { StringBuffer sb = new StringBuffer(); sb.append(FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath()); if (!resource.startsWith("/")) { sb.append("/"); } sb.append(resource); return sb.toString(); } /** * Search for the value of an attribute. * * @param context The Faces Context. * @param component The component on which the attribute has been set. * @param attributeName The name of the Attribute. * @return The value of the attribute, may be <code>null</code>. */ public static Object getAttributeValue(FacesContext context, UIComponent component, String attributeName) { Object value = component.getAttributes().get(attributeName); if (value != null) { return value; } // If value is null, this may indicates that attribute value is given as an EL expression. ValueExpression ve = component.getValueExpression(attributeName); if (ve != null) { return ve.getValue(context.getELContext()); } return null; } }
Nous sommes tous semblables, alors acceptons nos différences !
--------------------------------------------------------------
Liens : Blog | Page DVP | Twitter
Articles : Hudson | Sonar | Outils de builds Java Maven 3 | Play! 1 | TeamCity| CitConf 2009
Critiques : Apache Maven
toujours des erreurs
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 public class MyButtonRenderer extends ButtonRenderer { public OpmButtonRenderer() { super(); }
Je ne vois pas du tout comment appeller le composant dans la page
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 public final class MyComponentUtils { private OpmComponentUtils() { } ValueExpression ve = component.getValueExpression(attributeName); if (ve != null) { return ve.getValue(context.getELContext());
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 <a4j:page xlmns="http://www.3.org/1999/xhtml" xmlns:stephane="http://stephane/jsf"> <stephane:button/> </a4j:page>
Des erreurs ? C'est qu'il te manque les bonnes libraires JSF alors...
Dans ce code, tu "appelles" le composant. Il s'agit là d'un exemple d'une page écrite en XHTML. Ce serait grosso modo la même chose avec une page JSP.
Le fait d'écrire <stephane:button .../> dans cette page indique à JSF que lorsqu'il créera la page HTML, il créera un composant de type Button. C'est son renderer (la classe MyButtonRenderer) qui se chargera d'écrire le code HTML correspondant au composant.
Est-ce plus clair ?
Nous sommes tous semblables, alors acceptons nos différences !
--------------------------------------------------------------
Liens : Blog | Page DVP | Twitter
Articles : Hudson | Sonar | Outils de builds Java Maven 3 | Play! 1 | TeamCity| CitConf 2009
Critiques : Apache Maven
yes merci,pour mes erreurs pourtant j'utilise les lib jsf1.2 et uicomponent est bien présent mais n'a pas la méthode getValueExpression
Si tu as un souci avec getValueExpression, supprime la méthode getAttributeValue() de ma classe MyComponentUtils. Elle n'est pas utile dans mon exemple.
Edit : Pourtant, la méthode getValueExpression() existe bien dans UIComponent depuis la version 1.2 de JSF (voir ici).
Dans ton classpath, peut-être y a-t'il une librairie contenant une version plus ancienne de UIComponent. Ce qui expliquerait qu'il ne réussisse pas à trouver cette méthode.
Nous sommes tous semblables, alors acceptons nos différences !
--------------------------------------------------------------
Liens : Blog | Page DVP | Twitter
Articles : Hudson | Sonar | Outils de builds Java Maven 3 | Play! 1 | TeamCity| CitConf 2009
Critiques : Apache Maven
ok,mais je suis navré je ne vois pas du tout comment appeller mon composant
Il me met impossible de trouver l'uri http://stephane/jsf
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 <%@taglib uri="http://stephane/jsf" prefix="comp"%> <comp:button value="coucou"/>
J'ai essayé d'aprés ta balise <a4ij met je ne la posséde pas,j'ai vu que c'est du ajax,si j'ai envi d'appeller uniquement ce composent,comment dois je procéder?
Te fille tout ma partie de mon code permettant de créer le composant
pagination.jsp
Faces-config.xml
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 <%@taglib uri="/WEB-INF/stephane.taglib.tld" prefix="d"%> <d:button value="coucou"/>
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 <faces-config> <component> <component-type>buttonType</component-type> <component-class>composant.MyHtmlButton</component-class> </component> <render-kit> <render-kit-id>HTML_BASIC</render-kit-id> <renderer> <component-family>javax.faces.Command</component-family> <renderer-type>my.renderkit.button</renderer-type> <renderer-class>composant.MyButtonRenderer</renderer-class> </renderer> </render-kit>
stephane.taglib.tld
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>d</short-name> <uri>/WEB-INF/stephane.taglib.tld</uri> <tag> <name>buttonType</name> <tag-class>composant.MyButtonRenderer</tag-class> <body-content>JSP</body-content> </tag> </taglib>
MyButtonRenderer .java
MyHtmlButton
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 package composant; import java.io.IOException; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import com.sun.faces.renderkit.html_basic.ButtonRenderer; public class MyButtonRenderer extends ButtonRenderer { public void encodeBegin(FacesContext context, UIComponent component) throws IOException { ResponseWriter writer = context.getResponseWriter(); String buttonType = getButtonType(component); writer.startElement("table", null); writer.writeAttribute("border", "0", "table"); writer.writeAttribute("cellpadding", "0", "table"); writer.writeAttribute("cellspacing", "0", "table"); writer.startElement("tr", null); writer.startElement("td", null); writer.startElement("img", null); writer.writeAttribute("src", MyComponentUtils.getResourceUrl("images/button_" + buttonType + "_left.gif"), "img"); writer.endElement("img"); writer.endElement("td"); writer.startElement("td", null); component.getAttributes().put("styleClass", buttonType + "Button"); super.encodeBegin(context, component); } public void encodeEnd(FacesContext context, UIComponent component) throws IOException { super.encodeEnd(context, component); ResponseWriter writer = context.getResponseWriter(); writer.endElement("td"); writer.startElement("td", null); writer.startElement("img", null); writer.writeAttribute("src", MyComponentUtils.getResourceUrl("images/button_" + getButtonType(component) + "_right.gif"), "img"); writer.endElement("img"); writer.endElement("td"); writer.endElement("tr"); writer.endElement("table"); } private String getButtonType(UIComponent component) { String type = (String) component.getAttributes().get("buttonType"); if ((type != null) && (type.equalsIgnoreCase("std") || type.equalsIgnoreCase("default"))) { return type.toLowerCase(); } return MyComponentUtils.DEFAULT_BUTTON_CSS_CLASS; } }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 package composant; import javax.faces.component.html.HtmlCommandButton; import javax.faces.context.FacesContext; import javax.faces.el.ValueBinding; public class MyHtmlButton extends HtmlCommandButton{ private String buttonType; public String getButtonType() { if(buttonType!=null){ return buttonType; } ValueBinding vb=getValueBinding("buttonType"); if(vb!=null){ return(String)vb.getValue(getFacesContext()); } return null; } public void setButtonType(String buttonType) { this.buttonType = buttonType; } public void restoreState(FacesContext context,Object state){ Object values[]=(Object[])(Object[])state; super.restoreState(context,values[0]); buttonType=(String)values[1]; } public Object saveState(FacesContext context){ Object[] values=new Object[2]; values[0]=super.saveState(context); values[1]=buttonType; return (Object)values; } }
Je suppose étant donné qu'il connait le tag,que c'est un probléme vennant plutot de MyHtmlButton,mauvais lien....
Regarde please si ce sont les bons liens dans le fichier tld et xml
Je ne sais pas si ton problème vient de là, mais de mon exemple, je définis les composants dans un facelet-taglib, c'est-à-dire un fichier blabla.taglib.xml, tandis que toi, tu as opté pour un fichier taglib (blabla.tld).
Nous sommes tous semblables, alors acceptons nos différences !
--------------------------------------------------------------
Liens : Blog | Page DVP | Twitter
Articles : Hudson | Sonar | Outils de builds Java Maven 3 | Play! 1 | TeamCity| CitConf 2009
Critiques : Apache Maven
je sais mais j'ai essayé directement ta facon,marche pas non plus,et comme j'ai vu sur un site que c'est un fichier tld,j'ai tenté le coup
Une petite question,comment il peut savoir c'est qu'elle fichier xml qui contient le composant créer(stephane.taglib.xml)
Sinon,si t'aurais deja un petit projet simple que je puisse comprendre comprennant biensur la création d'un composant si possible un bouton arrondie,car il faut que j'en insére un à mon projet,ca serait![]()
Si je ne dis pas de bétise, JSF (facelets) va charger tous les les fichiers *taglib.xml qu'il trouve dans le classpath.
Chacun de ces fichier à un namespace particulier :
(le namespace ne correspond à rien en soit, ce n'est pas vraiment une URL, mais plutôt un identifiant)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4<facelet-taglib> <namespace>http://bla.bla.bla/jsf</namespace> ...
Ensuite, dans le fichier JSP ou XHTML, il faut indiquer que tu utilises ce namespace en précisant quel préfix tu utilises pour les composants sur ta page :
ou
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 <%@taglib uri="http://bla.bla.bla/jsf" prefix="bla" %>
Enfin, tu n'as plus qu'à utiliser le composant en le préfixant correctement :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3<h:page xmlns:bla="http://bla.bla.bla/jsf"> ...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 <bla:monComposant ...>
Nous sommes tous semblables, alors acceptons nos différences !
--------------------------------------------------------------
Liens : Blog | Page DVP | Twitter
Articles : Hudson | Sonar | Outils de builds Java Maven 3 | Play! 1 | TeamCity| CitConf 2009
Critiques : Apache Maven
en mettant n'importe qu'elle nom,je ne vois plus le tag
Nous sommes tous semblables, alors acceptons nos différences !
--------------------------------------------------------------
Liens : Blog | Page DVP | Twitter
Articles : Hudson | Sonar | Outils de builds Java Maven 3 | Play! 1 | TeamCity| CitConf 2009
Critiques : Apache Maven
dans l'uri j ai mis http;//stephane.jsf
Et dans la page jsp,lorsque je fais le <prefix:,cette fois ci il trouve quedal tandis que si je mets le chemin vers le fichier xml,i trouve bien mais bon,dans les deux cas,ca ne marchent pas![]()
Partager