Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Shale Wiki" for change 
notification.

The following page has been changed by Hermod Opstvedt:
http://wiki.apache.org/shale/CreatingClayComponents

------------------------------------------------------------------------------
  If you started with the Maven2 archetype, the person bean will already have 
been defined as a managed bean in the faces-config.xml file, if not enter this 
into it:
  
  {{{
-     <managed-bean id="person">[[BR]]
+     <managed-bean id="person">
-         <managed-bean-name>person</managed-bean-name>[[BR]]
+         <managed-bean-name>person</managed-bean-name>
-         <managed-bean-class>[[BR]]
+         <managed-bean-class>
-             com.acme.test.Person[[BR]]
+             com.acme.test.Person
-         </managed-bean-class>[[BR]]
+         </managed-bean-class>
-         <managed-bean-scope>session</managed-bean-scope>[[BR]]
+         <managed-bean-scope>session</managed-bean-scope>
-     </managed-bean>[[BR]]
+     </managed-bean>
  }}}
  
  Now we almost have the receiver for the data in place. What we lack is a 
viewcontroller (controller in MVC) for the person registration form. Create a 
bean PersonVC that extends Abstract``View``Controller and has one attribute of 
type Person with respective getter/setter.
@@ -48, +48 @@

  Define the following in faces-config.xml file
  
  {{{
-     <managed-bean id="personReg">[[BR]]
+     <managed-bean id="personReg">]
-         <managed-bean-name>personReg</managed-bean-name>[[BR]]
+         <managed-bean-name>personReg</managed-bean-name>]
-         <managed-bean-class>[[BR]]
+         <managed-bean-class>]
-             com.acme.test.PersonVC[[BR]]
+             com.acme.test.PersonVC]
-         </managed-bean-class>[[BR]]
+         </managed-bean-class>]
-         <managed-bean-scope>request</managed-bean-scope>[[BR]]
+         <managed-bean-scope>request</managed-bean-scope>]
-         <managed-property>[[BR]]
+         <managed-property>]
-             <property-name>person</property-name>[[BR]]
+             <property-name>person</property-name>]
-             <property-class>[[BR]]
+             <property-class>]
-                 com.acme.test.Person[[BR]]
+                 com.acme.test.Person]
-             </property-class>[[BR]]
+             </property-class>]
-             <value>#{person}</value>[[BR]]
+             <value>#{person}</value>]
-         </managed-property>[[BR]]
+         </managed-property>]
-     </managed-bean>[[BR]]
+     </managed-bean>]
  }}}
  
  The next we do is to add a method that "saves" the person. Do this by adding 
the following method:
  
  {{{
-     public String save()[[BR]]
+     public String save()
-     {[[BR]]
+     {
-         return null;[[BR]]
+         return null;
-     }[[BR]]
+     }
  }}}
  
  For now this method does nothing. Also note that it returns null. This means 
that no navigation rule will be executed and we remain at the same form.
@@ -84, +84 @@

  We start by creating the generic labell/input filed component and we will 
call it "gltic". This is short for Generic Label Text Input Component.
  
  {{{
-     <component jsfid="gltic" extends="clay" id="gltic">[[BR]]
+     <component jsfid="gltic" extends="clay" id="gltic">]
-         <element jsfid="outputLabel" renderId="1">[[BR]]
+         <element jsfid="outputLabel" renderId="1">]
-             <attributes>[[BR]]
+             <attributes>]
-                 <set name="value" value="@ltName"></set>[[BR]]
+                 <set name="value" value="@ltName"></set>]
-             </attributes>[[BR]]
+             </attributes>]
-         </element>[[BR]]
+         </element>]
-         <element jsfid="inputText" renderId="2">[[BR]]
+         <element jsfid="inputText" renderId="2">]
-             <attributes>[[BR]]
+             <attributes>]
-                 <set name="value" value="@ltValue"></set>[[BR]]
+                 <set name="value" value="@ltValue"></set>]
-             </attributes>[[BR]]
+             </attributes>]
-         </element>[[BR]]
+         </element>]
-     </component>[[BR]]
+     </component>]
  }}}
  
  There are a couple of things to note here. Firstsly, we extend from "clay". 
All components must either extend "clay" or another existing component. Next 
thing to note is that within the component define elements that are part of the 
component. Be careful with the rendered attribute. This attribute governs the 
rendering order of the elements to the device. So be careful to order them in 
the order that you want them displayed. Also take care that the renderIDs are 
unique at the same element level (You can have nested elements).
@@ -105, +105 @@

  Lets now try to define the first panel, which is the name panel. As we said 
earlier there are a lot of ready-made component libraries for us to choose 
from. We are now going to use one of these. It is know as 
[http://myfaces.apache.org/tomahawk/index.html/ Tomahawk] and comes from the 
[http://myfaces.apache.org/ MyFaces project]. The component that we are going 
to use is the [http://myfaces.apache.org/tomahawk/htmlTag.html/ htmlTag]. This 
is a component that will render any HTML tag that you specify as a value. To be 
able to use this, you need to download it and install it into you project. How 
you do this depends on whether you are using the Maven2 plugin, Maven2 by it 
self or not at all. The important thing is that you get the tomahawk jar file 
in the WEB-INF/LIB  when you deploy your application(if it’s a standalone 
WAR). We base our application on the latest version which is currently 
1.5-SNAPSHOT. Next is to make Clay aware of the components. You do that by 
adding th
 e attachment:tomahawk-1.1.5-SNAPSHOT-config.xml Clay configuration file to 
your WEB-INF folder. Then change the following section in the web.xml file:
  
  {{{
-     <!-- Clay Common Configuration Resources -->[[BR]]
+     <!-- Clay Common Configuration Resources -->]
-     <context-param>[[BR]]
+     <context-param>]
-         <param-name>[[BR]]
+         <param-name>]
-             org.apache.shale.clay.COMMON_CONFIG_FILES[[BR]]
+             org.apache.shale.clay.COMMON_CONFIG_FILES]
-         </param-name>[[BR]]
+         </param-name>]
-         <param-value>[[BR]]
+         <param-value>]
-             /WEB-INF/clay-config.xml,[[BR]]
+             /WEB-INF/clay-config.xml,]
-             /WEB-INF/tomahawk-1.1.5-SNAPSHOT-config.xml[[BR]]
+             /WEB-INF/tomahawk-1.1.5-SNAPSHOT-config.xml]
-         </param-value>[[BR]]
+         </param-value>]
-     </context-param>[[BR]]
+     </context-param>]
  }}}
  
  We are now ready to use all the components that Tomahawk has to offer.
@@ -122, +122 @@

  Back to our name panel, there is one thing that we need to decide. What to 
use as the outermost container? As you may know JSF builds a component tree and 
uses POST to send data from the client to the server and that requires a form. 
Since we are going to add more components to our page that carry data, we 
choose to use a tag that is frequently (container) used within a form: 
Fieldset. So this will be our container. Now our componet looks likes this:
  
  {{{
-     <component jsfid="namepanel" extends="clay" id="namepanel">[[BR]]
+     <component jsfid="namepanel" extends="clay" id="namepanel">]
-         <element jsfid="t:htmlTag" renderId="1" id="namefieldset">[[BR]]
+         <element jsfid="t:htmlTag" renderId="1" id="namefieldset">]
-             <attributes>[[BR]]
+             <attributes>]
-                 <set name="value" value="fieldset" />[[BR]]
+                 <set name="value" value="fieldset" />]
-             </attributes>[[BR]]
+             </attributes>]
-             <element jsfid="t:htmlTag" renderId="1" id="namelegend">[[BR]]
+             <element jsfid="t:htmlTag" renderId="1" id="namelegend">]
-                 <attributes>[[BR]]
+                 <attributes>]
-                     <set name="value" value="legend" />[[BR]]
+                     <set name="value" value="legend" />]
-                 </attributes>[[BR]]
+                 </attributes>]
-                 <element jsfid="outputText" renderId="1">[[BR]]
+                 <element jsfid="outputText" renderId="1">]
-                     <attributes>[[BR]]
+                     <attributes>]
-                         <set name="value"[[BR]]
+                         <set name="value"]
-                             value="#{messages['namepanel.text']}">[[BR]]
+                             value="#{messages['namepanel.text']}">]
-                         </set>[[BR]]
+                         </set>]
-                     </attributes>[[BR]]
+                     </attributes>]
-                 </element>[[BR]]
+                 </element>]
-             </element>[[BR]]
+             </element>]
-             <element jsfid="gltic" renderId="2" id="firstname">[[BR]]
+             <element jsfid="gltic" renderId="2" id="firstname">]
-                 <symbols>[[BR]]
+                 <symbols>]
-                     <set name="ltName"[[BR]]
+                     <set name="ltName"]
-                         value="#{messages['firstname.label']}">[[BR]]
+                         value="#{messages['firstname.label']}">]
-                     </set>[[BR]]
+                     </set>]
-                     <set name="ltValue"[[BR]]
+                     <set name="ltValue"]
-                         value="[EMAIL PROTECTED]'firstname']}">[[BR]]
+                         value="[EMAIL PROTECTED]'firstname']}">]
-                     </set>[[BR]]
+                     </set>]
-                 </symbols>[[BR]]
+                 </symbols>]
-             </element>[[BR]]
+             </element>]
-             <element jsfid="t:htmlTag" renderId="3" id="navnbr">[[BR]]
+             <element jsfid="t:htmlTag" renderId="3" id="navnbr">]
-                 <attributes>[[BR]]
+                 <attributes>]
-                     <set name="value" value="br" />[[BR]]
+                     <set name="value" value="br" />]
-                 </attributes>[[BR]]
+                 </attributes>]
-             </element>[[BR]]
+             </element>]
-             <element jsfid="gltic" renderId="4" id="lastname">[[BR]]
+             <element jsfid="gltic" renderId="4" id="lastname">]
-                 <symbols>[[BR]]
+                 <symbols>]
-                     <set name="ltName"[[BR]]
+                     <set name="ltName"]
-                         value="#{messages['lastname.label']}">[[BR]]
+                         value="#{messages['lastname.label']}">]
-                     </set>[[BR]]
+                     </set>]
-                     <set name="ltValue"[[BR]]
+                     <set name="ltValue"]
-                         value="[EMAIL PROTECTED]'lastname']}">[[BR]]
+                         value="[EMAIL PROTECTED]'lastname']}">]
-                     </set>[[BR]]
+                     </set>]
-                 </symbols>[[BR]]
+                 </symbols>]
-             </element>[[BR]]
+             </element>]
-         </element>[[BR]]
+         </element>]
-     </component>[[BR]]
+     </component>]
  }}}
  
  
@@ -178, +178 @@

  We now have a panel where we can enter firstname and lastname. But we also 
need a panel to enter the address information. As we mentioned earlier this 
time we define the component in HTML. The principals are the same, only now we 
are using HTML and are able to do preview on what we do. The panel then becomes 
(stripped):
  
  {{{
-             <fieldset>[[BR]]
+             <fieldset>]
-                 <legend>[[BR]]
+                 <legend>]
-                     <span jsfid="outputText" value="@adresslegend" 
allowbody="false">Adress</span>[[BR]]
+                     <span jsfid="outputText" value="@adresslegend" 
allowbody="false">Adress</span>]
-                 </legend>[[BR]]
+                 </legend>]
-                 <label jsfid="outputLabel" value="@streetadressLabel" 
allowbody="false">[[BR]]
+                 <label jsfid="outputLabel" value="@streetadressLabel" 
allowbody="false">]
-                     Streetadress[[BR]]
+                     Streetadress]
-                 </label>[[BR]]
+                 </label>]
-                 <input jsfid="inputText" value="@streetadressField" 
type="text" allowbody="false">[[BR]]
+                 <input jsfid="inputText" value="@streetadressField" 
type="text" allowbody="false">]
-                 <br>[[BR]]
+                 <br>]
-                 <label jsfid="outputLabel" value="@zipcodeLabel" 
allowbody="false">[[BR]]
+                 <label jsfid="outputLabel" value="@zipcodeLabel" 
allowbody="false">]
-                     Zipcode[[BR]]
+                     Zipcode]
-                 </label>[[BR]]
+                 </label>]
-                 <input jsfid="inputText" value="@zipcodeField" type="text" 
allowbody="false">[[BR]]
+                 <input jsfid="inputText" value="@zipcodeField" type="text" 
allowbody="false">]
-                 <br>[[BR]]
+                 <br>]
-                 <label jsfid="outputLabel" value="@cityLabel" 
allowbody="false">[[BR]]
+                 <label jsfid="outputLabel" value="@cityLabel" 
allowbody="false">]
-                     City[[BR]]
+                     City]
-                 </label>[[BR]]
+                 </label>]
-                 <input jsfid="inputText" value="@cityField" type="text" 
allowbody="false">[[BR]]
+                 <input jsfid="inputText" value="@cityField" type="text" 
allowbody="false">]
-             </fieldset>[[BR]]
+             </fieldset>]
  }}}
  
  As you can see this is pure HTML with some special attributes on some of the 
HTML tags. These attributes are Clay directives. The attribute "jsfid" points 
at a Clay component defined in a Clay configuration file. Next is "value" where 
we which value the tag should have. Since this is to be a reusable component, 
we use the symbol instead of hardcoded values. The "SPAN" tag is used as a 
replacement for the cases where we want to simply output some text that is not 
related to any tag. We save this in the pages folder and give it a name of 
adresspanel.html.
@@ -204, +204 @@

  Now that we have defined our HTML based Clay component, we need to tell Clay 
of its existence. We do that by adding the following in our clay-config.xml 
file;
  
  {{{
-     <component jsfid="adresspanel" extends="clay" id="adresspanel">[[BR]]
+     <component jsfid="adresspanel" extends="clay" id="adresspanel">]
-         <attributes>[[BR]]
+         <attributes>]
-             <set name="clayJsfid" value="/pages/adresspanel.html" />[[BR]]
+             <set name="clayJsfid" value="/pages/adresspanel.html" />]
-         </attributes>[[BR]]
+         </attributes>]
-     </component>[[BR]]
+     </component>]
  }}}
  
  Note that we here use a special attribute "clayJsfid". This is Clay's variant 
of including something (ala jsp:include). So here we import our HTML component 
and assign it a Clay id (jsfid).
@@ -234, +234 @@

  SO lets stitch this together as a whole. Since we are not adding any more 
components to our page, we can use the form as basis for it. Our completed 
component then becomes:
  
  {{{
-     <component jsfid="personregpanel" extends="form"[[BR]]
+     <component jsfid="personregpanel" extends="form"]
-         id="personregpanel">[[BR]]
+         id="personregpanel">]
-         <element jsfid="namepanel" renderId="1"></element>[[BR]]
+         <element jsfid="namepanel" renderId="1"></element>]
-         <element jsfid="t:htmlTag" renderId="2" id="pbr">[[BR]]
+         <element jsfid="t:htmlTag" renderId="2" id="pbr">]
-             <attributes>[[BR]]
+             <attributes>]
-                 <set name="value" value="br" />[[BR]]
+                 <set name="value" value="br" />]
-             </attributes>[[BR]]
+             </attributes>]
-         </element>[[BR]]
+         </element>]
-         <element jsfid="adresspanel" renderId="3">[[BR]]
+         <element jsfid="adresspanel" renderId="3">]
-             <symbols>[[BR]]
+             <symbols>]
-                 <set name="adresslegend" 
value="#{messages['adresspanel.text']}"></set>[[BR]]
+                 <set name="adresslegend" 
value="#{messages['adresspanel.text']}"></set>]
-                 <set name="streetadressLabel" 
value="#{messages['streetadress.label']}"></set>[[BR]]
+                 <set name="streetadressLabel" 
value="#{messages['streetadress.label']}"></set>]
-                 <set name="streetadressFeield" value="[EMAIL 
PROTECTED]'streetadress']}"></set>[[BR]]
+                 <set name="streetadressFeield" value="[EMAIL 
PROTECTED]'streetadress']}"></set>]
-                 <set name="zipcodeLabel" 
value="#{messages['zipcode.label']}"></set>[[BR]]
+                 <set name="zipcodeLabel" 
value="#{messages['zipcode.label']}"></set>]
-                 <set name="zipcodeFelt" value="[EMAIL 
PROTECTED]'zipcode']}"></set>[[BR]]
+                 <set name="zipcodeFelt" value="[EMAIL 
PROTECTED]'zipcode']}"></set>]
-                 <set name="cityLabel" 
value="#{messages['city.label']}"></set>[[BR]]
+                 <set name="cityLabel" 
value="#{messages['city.label']}"></set>]
-                 <set name="cityField" value="[EMAIL 
PROTECTED]'city']}"></set>[[BR]]
+                 <set name="cityField" value="[EMAIL 
PROTECTED]'city']}"></set>]
-             </symbols>[[BR]]
+             </symbols>]
-         </element>[[BR]]
+         </element>]
-         <element jsfid="t:htmlTag" renderId="4" id="pbr2">[[BR]]
+         <element jsfid="t:htmlTag" renderId="4" id="pbr2">]
-             <attributes>[[BR]]
+             <attributes>]
-                 <set name="value" value="br" />[[BR]]
+                 <set name="value" value="br" />]
-             </attributes>[[BR]]
+             </attributes>]
-         </element>[[BR]]
+         </element>]
-         <element jsfid="saveButton" renderId="5">[[BR]]
+         <element jsfid="saveButton" renderId="5">]
-             <symbols>[[BR]]
+             <symbols>]
-                 <set name="metode" value="save"></set>[[BR]]
+                 <set name="metode" value="save"></set>]
-             </symbols>[[BR]]
+             </symbols>]
-         </element>[[BR]]
+         </element>]
-     </component>[[BR]]
+     </component>]
  }}}
  
  Here we have defined our reusable components as elements (respecting the 
rendered) and defined actual values to substitute the symbols with.
@@ -284, +284 @@

  To refine this you can substitute the zipcode field with a combobox that gets 
its values from the Post beans getZipcodes method (This is shown in the 
downloadable finished application). The HTML definition for it is:
  
  {{{
-         <select value="@zipcodeFelt" allowBody="true">[[BR]]
+         <select value="@zipcodeFelt" allowBody="true">
-             <option value="@zipcodesList" />[[BR]]
+             <option value="@zipcodesList" />
-         </select>[[BR]]
+         </select>
  }}}
  
  In addition we also have to declare what the symbol "zipcodesList" is to be 
replaced with when we use it on our page.
@@ -295, +295 @@

  
[http://java.sun.com/javaee/javaserverfaces/1.1_01/docs/api/javax/faces/model/SelectItem.html/
  SelectItem] '''Select''Item[]''', Collection or Map. We use Select``Item, so 
you need to add the following method to the Post bean:
  
  {{{
-     private void initZipcodesList() {[[BR]]
+     private void initZipcodesList() {]
-         zipcodeliste=new Select``Item[zipcodes.length];[[BR]]
+         zipcodeliste=new Select``Item[zipcodes.length];]
-         Select``Item selectItem;[[BR]]
+         Select``Item selectItem;]
-         for(int i=0; i < zipcodes.length; i++)[[BR]]
+         for(int i=0; i < zipcodes.length; i++)]
-         {[[BR]]
+         {]
-             selectItem=new Select``Item();[[BR]]
+             selectItem=new Select``Item();]
-             selectItem.setLabel(zipcodes[i].toString());[[BR]]
+             selectItem.setLabel(zipcodes[i].toString());]
-             selectItem.setValue(zipcodes[i]);[[BR]]
+             selectItem.setValue(zipcodes[i]);]
-             zipcodesliste[i]=selectItem;[[BR]]
+             zipcodesliste[i]=selectItem;]
-         }[[BR]]
+         }]
-         [[BR]]
+         ]
-     }[[BR]]
+     }]
  {{{
  
  And add a default constructor to it:
  
  {{{
-     public Post()[[BR]]
+     public Post()
-     {[[BR]]
+     {
-         initZipcodesList();[[BR]]
+         initZipcodesList();
-     }[[BR]]
+     }
  }}}
  
  When you run this it will look like this:

Reply via email to