<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Sealyu

    --- 博客已遷移至: http://www.sealyu.com/blog

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      618 隨筆 :: 87 文章 :: 225 評論 :: 0 Trackbacks

    Creating Custom Components with JSF and Facelets

    Creating custom components with JSF and Facelets is NOT the same as creating custom JSF components with JSP. If you search on the internet for custom JSF components you will get messed up, confused, and nothing is seemingly clear. Its actually relatively easy to create a custom component with Facelets relative to JSP. Allot less code is required and only a few configuration files need to be modified/added.

    There are four main steps in creating a custom component with JSF and Facelets.

    1. Create a facelet-taglib for your custom tag named something like myTags.taglib.xml . Also make sure this file is copied over to the EAR file in the META-INF directory. This is usually done through your build.xml under the target to build your EAR.
      ..

      http://mystuff.com/mycomponent

      mycomponent

      com.mystuff.mycomponent

      com.mystuff.components.mycomponent

    2. Next let JSF and Facelets know of your new component by adding it to /WEB-INF/faces-config.xml.
      ...   

      com.mystuff.mycomponent

      com.mystuff.components.MyComponent

      ...

    3. Create the java code to render the component. To do this you need to remember a few things. 
      1. Extend from the UIComponentBase class or any class that is a child of it.
      2. @Override getFamily , which should return the component type ( the same name as in he facelet-taglib and faces-config ).
      3. @Override encodeBegin and/or encodeEnd for outputting the componenet’s markup. Its good practice to use the response writer’s methods to start elements, add attributes to them, and to end elements.
      4. Provide getters and setters for your attributes.
      5. Be Careful!!!
        If your component is used on a page with a form, and you throw exceptions for required values, then you must implement saveState and restoreState. If not the JSF lifecycle will try to recreate the component on the restoreView phase upon an invalid form entry. If not present the required exception is thrown since the value no longer exists.
    4.  

      public MyComponent(){

        super();

        setRendererType(null)

        }   



      @Override



      public String getFamily(){



        return COMPONENT_TYPE;



        }



      @Override

        public void encodeBegin(FacesContext context) throws IOException{



        super.encodeBegin(context);



        final ResponseWriter writer = context.getResponseWriter();



        writer.write(""n");


        writer.writeComment(" BEGIN MYCOMPONENT INCLUDE ");





        writer.write(""n");





        if(this.getRenderIncludes()){





        String jsURL = context.getExternalContext().getRequestContextPath() + JS_DIR + "/" + JS_FILE;



        writer.startElement("script", null);

        writer.writeAttribute("type", "text/javascript", null);

        writer.writeAttribute("src", jsURL, null);

        writer.endElement("script");

        writer.write(""n");

        String jsURL2 = context.getExternalContext().getRequestContextPath() + JS_DIR + "/" + JS_FILE_2;

        writer.startElement("script", null);

        writer.writeAttribute("type", "text/javascript", null);

        writer.writeAttribute("src", jsURL2, null);

        writer.endElement("script");

        writer.write(""n");

        }

        writer.startElement("script", null);

        writer.write(""n");

        writer.write("createMyComponentTag(");

        writer.write("'" + getPageId() + "', ");

        writer.write("'" + getTemplateId() + "', ");

        writer.write("null, ");

        writer.write("'" + getCategoryId() + "', ");

        writer.write("null, ");

        writer.write("null, ");

        writer.write("null, ");

        writer.write("null, ");

        writer.write("null, ");

        writer.write("null, ");

        writer.write("null, ");

        writer.write("null, ");

        writer.write("null);"n");

        writer.write(""n");

        writer.endElement("script");

        writer.write(""n");

        writer.writeComment(" END MYCOMPONENT INCLUDE ");

        }



      @Override

        public void encodeEnd(FacesContext context) throws IOException{

        super.encodeEnd(context);

        }



      public String getPageId(){

        if(null != this.pageId){

        return this.pageId;

        }

        ValueExpression ve = getValueExpression("pageId");

        if(ve == null){

        throw new javax.el.ELException("Value for mystuff mycomponent Tag: 'pageId' is required");

        }

        return (String) ve.getValue(getFacesContext().getELContext());

        }



      public void setPageId(String pageId){

        this.pageId = pageId;

        }

    5. Now using your custom component is as easy as adding the namespace and adding the tag to your Facelet. 

    Other techniques for saving and restoring state, adding ajax functionality through phase listeners, and determining if you need to implement ActionSource, ValueHolder, or EditableValueHolder into your component can be searched on the internet. A good source of Facelets documentation is here https://facelets.dev.java.net/nonav/docs/dev/docbook.html .

    Here is an example I added to show an easy custom component.

    custom-pmc-ui1.zip

    Its from the SEAM examples of the jboss-seam-2.0.2.SP1 release. Just add this to the examples folder of you SEAM directory.
    Its path is “{SEAM_HOME}/examples/ui” . I’ve just added a package called “org.mcjury.components”, a class for the component “TableNameComponent.java”, a facelet called “tableName.xhtml”, an xml file called “META-INF/table-component.taglib.xml”, and lastly edited “faces.config.xml” to register the component.

    The usage is followed by a couple of examples of my custom table component and a use of the entity-manager with a h:dataTable.

    To deploy just run “ant” in the “examples/ui” folder. If you have seam set up right it should copy over the EAR to you jboss server deploy directory. The jboss home is set in your “build.properties” in the root of the SEAM directory. If its not there just add this
    “jboss.home=/PATH/TO/JBOSS/jboss-4.2.2.GA”
    to it and you should be all set. Than start up jboss with “run.sh”.



    Writing Custom Components in JSF + Facelets PDF Print E-mail
    Mar 20, 2007 at 03:27 PM

    One of the misleading parts for me was that available articles treating "custom JSF component creation" around are targetting JSF components used within JSP pages. If you're using Facelets (a JSP independent view-handler for JSF - see http://facelets.dev.java.net) things are slightly different. At least it seems to be easier to create custom components with Facelets than doing it with JSP.

    Hopefully to provide some help, I'll shortly describe the steps necessary for me to build my first
    custom JSF component within a Facelets web-app:

    1. Tell Facelets to load your custom taglibrary. Add something like this to your web.xml file:  

    <context-param>
        <param-name>facelets.LIBRARIES</param-name>
        <param-value>/WEB-INF/facelets/my.taglib.xml</param-value>
    </context-param>

    The xml file above is treated as tag-library for the facelets framework similar as we know it from JSP (the tld files). You can add all your custom tags/components into this file. Basically it should look like this:

    2. Create a facelets-taglib for your custom tags:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE facelet-taglib PUBLIC
    "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
    "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
    <facelet-taglib>
        <namespace>http://org.zapto.hanzz/mytags</namespace>
        <tag>
            <tag-name>rdolink</tag-name>
            <component>
                <component-type>hanzz.RdoLinkComponent</component-type>
            </component>
        </tag>
        <tag>
            <tag-name>rdocoll</tag-name>
            <component>
                <component-type>hanzz.RdoCollComponent</component-type>
            </component>
        </tag>
    </facelet-taglib>

    3. Publish your custom components to JSF in faces-config.xml. Add something like this:

        <component>
            <component-type>hanzz.RdoLinkComponent</component-type>
            <component-class>org.zapto.hanzz.jsf.RdoLinkComponent</component-class>
        </component>
         <component>
            <component-type>hanzz.RdoCollComponent</component-type>
            <component-class>org.zapto.hanzz.jsf.RdoCollComponent</component-class>
        </component>
        
    As you can see - the <component-type> element in faces-config.xml maps the facelet-tag's <component-type> element as visible above. This is the way how facelets can map a custom tag within a XML file to a JSF component and JSF can map the component type to a specific implementation - the Java Class.

    4. Write the corresponding Java Class(es).
    This is where it gets specific: Depending on the requirements of your custom component the class should be derived from a JSF base component. In my example I had to write a selectOneRadio that was able to render the radio-buttons label with a http-link to a descriptive text. Therefore my custom component was derived from UISelectOne:

    public class RdoLinkComponent extends UISelectOne {
        /** Creates a new instance of RdoLinkComponent */
        public RdoLinkComponent() {
            super();
        }
        public void encodeBegin(FacesContext context) throws IOException {
            final ResponseWriter writer = context.getResponseWriter();
            final String clientId = getClientId(context);
            
            RdoCollComponent childColl = null;
            for (UIComponent comp : getChildren()) {
                if(comp instanceof RdoCollComponent) {
                    childColl = (RdoCollComponent) comp;
                }
            }      
            if((childColl==null)||(childColl.getValue()==null)) {
                writer.writeText("Keine Produkte verfügbar.",null);
            } else {
                Collection<Product> prods = (Collection<Product>)childColl.getValue();
                for(Product prod:prods) {
                    encodeRadio(writer,prod,clientId);  
                }
            }
        }
        
        private void encodeRadio(ResponseWriter writer, PlcProduct prod, String clientId) throws IOException {
            writer.startElement("input",null);
            writer.writeAttribute("type","radio",null);
            writer.writeAttribute("name", clientId, "clientId");
            writer.writeAttribute("value", prod.getKey(), "value");
            writer.endElement("input");
            writer.startElement("a",null);
            writer.writeAttribute("href",prod.getDescUrl(),null);
            writer.writeAttribute("target","_blank",null);
            writer.writeText(prod.getLabel(),null);        
            writer.endElement("a");
        }

        public void encodeEnd(FacesContext context) throws IOException {
        }

        public void decode(FacesContext context) {
            Map requestMap = context.getExternalContext().getRequestParameterMap();
            final String clientId = getClientId(context);

            String string_submit_val = ((String) requestMap.get(clientId));
            setSubmittedValue(string_submit_val);
            setValid(true);  
        }
        
        public void encodeChildren(FacesContext context) throws IOException {
        }
        protected void validateValue(FacesContext context, Object value) {
            setValid(true);
        }

    The encodeXXX-methods are used to render the component into HTML, the decode method is used to read the components selected value of the submitted form. I won't explain that in more detail here - look at the methods in the example above, it should be straightforward to understand. For more information about encoding and decoding refer to the JSF docs.

    You can see that I've used a child component to assign the radio-groups select items but the
    rendering of the html- input tags is done right here in the parent class, so I created only a dummy implementation for the child RdoColl-Component:

    public class RdoCollComponent extends UIOutput {
        /** Creates a new instance of RdoCollComponent */
        public RdoCollComponent() {
        }
        public void encodeBegin(FacesContext context) throws IOException {   
        }
        public void encodeEnd(FacesContext context) throws IOException {
        }
        public void encodeChildren(FacesContext context) throws IOException {
        }
        public void decode(FacesContext context) {
        }
    }

    The above RdoColl-Component is used to "hold" the collection of possible options (i.e. the SelectItems) for the RdoLink-Component above. Implementing all of the above empty methods ensures that the child component does not produce any HTML output. I'm not sure if this is the state-of-the-art way to do this, basically it works fine in this case. I could not use the standard f:selectItems here because more than only a label and a value attribute is needed -  the URL for the link to the description of the product.

    5. Now we have written our custom components and publicized them to facelets/jsf, we simply can add it on the required .xhtml page like this:

    - add the namespace as defined in your facelet taglib and a prefix:
     xmlns:hanzz="http://org.zapto.hanzz/mytags"
     
    - use your tags:
     <hanzz:rdolink value="#{orderBean.selectedProduct}"   >
           <hanzz:rdocoll value="#{orderBean.availableProducts}"/>
     </hanzz:rdolink>

    posted on 2009-03-20 10:47 seal 閱讀(928) 評論(0)  編輯  收藏 所屬分類: Seam
    主站蜘蛛池模板: 亚洲中文字幕无码一去台湾| 亚洲四虎永久在线播放| 亚洲中文字幕无码爆乳| 黄色永久免费网站| 亚洲人成激情在线播放| 免费福利视频导航| 亚洲综合无码一区二区| 久久精品乱子伦免费| 久久久无码精品亚洲日韩蜜桃| 91在线视频免费观看| 国产亚洲精品a在线观看app| 可以免费观看的毛片| 亚洲国产精品一区| 91久久成人免费| 亚洲中文字幕久在线| 成人免费无码大片a毛片软件| 亚洲日韩精品A∨片无码加勒比| 成人免费福利电影| 免费精品视频在线| 国产亚洲一区二区手机在线观看 | 亚洲人成网站在线播放影院在线| 嫩草在线视频www免费看| 亚洲最新视频在线观看| 一级女人18毛片免费| 亚洲av日韩专区在线观看| 亚洲片国产一区一级在线观看| 国产精品永久免费视频| 亚洲国产精品lv| 成人au免费视频影院| 五月婷婷免费视频| 亚洲精品在线免费看| 国产午夜免费秋霞影院| 国产午夜无码片免费| 亚洲人成人77777在线播放| 又黄又爽一线毛片免费观看| 99精品免费视品| 亚洲日本va一区二区三区 | 亚洲一区精品中文字幕| 成年女人午夜毛片免费看| 国产乱子伦精品免费视频| 亚洲av午夜精品无码专区|