Using composite:insertFacet/renderFacet does not work inside t:dataTable

前端 未结 2 1548
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-19 10:11

I\'m doing this: resources/vm/table.xhtml:

...

  


        
相关标签:
2条回答
  • 2021-01-19 10:31

    SOLVED: I had to use insertChildren and then everything works :) Took me 1.5 days to find this... Now looks so simple. Migrating from RichFaces3.3.3/JSF1.2 to RichFaces4.0/JSF2 is a lot of work and a lot to learn. But I'm getting there :)

    resources/vm/table.xhtml:

    ...
    <composite:interface>
    </composite:interface>
    ...
    <composite:implementation>
      <t:dataTable>
        <composite:insertChildren/>
      </t:dataTable>
    </composite:implementation>
    ...
    

    And in page.xhtml:

    ...
    <vm:table>
      <t:column>
        Testing.
      </t:column>
    </vm:table>
    ...
    
    0 讨论(0)
  • 2021-01-19 10:38

    Here is the implentation of <cc:insertRawFacet> tag by myself, it works just like the ui:insert. Well, this is a MyFaces solution, though.

    import java.io.IOException;
    import java.lang.reflect.Field;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.logging.Logger;
    
    import javax.faces.component.UIComponent;
    import javax.faces.view.facelets.FaceletContext;
    import javax.faces.view.facelets.FaceletHandler;
    import javax.faces.view.facelets.FacetHandler;
    import javax.faces.view.facelets.TagConfig;
    import javax.faces.view.facelets.TagHandler;
    import javax.free.UnexpectedException;
    
    import org.apache.myfaces.view.facelets.AbstractFaceletContext;
    import org.apache.myfaces.view.facelets.TemplateClient;
    import org.apache.myfaces.view.facelets.TemplateContext;
    import org.apache.myfaces.view.facelets.TemplateManager;
    import org.apache.myfaces.view.facelets.tag.composite.CompositeComponentResourceTagHandler;
    import org.apache.myfaces.view.facelets.tag.composite.InsertFacetHandler;
    
    public class InsertRawFacetHandler
            extends InsertFacetHandler {
    
        static final Logger logger = Logger.getLogger(InsertRawFacetHandler.class.getName());
    
        public InsertRawFacetHandler(TagConfig config) {
            super(config);
        }
    
        @Override
        public String getFacetName(FaceletContext ctx) {
            return _name.getValue(ctx);
        }
    
        @Override
        public void apply(FaceletContext ctx, UIComponent parent)
                throws IOException {
            String facetName = _name.getValue(ctx);
    
            AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
            // actx.includeCompositeComponentDefinition(parent, facetName);
            TemplateClient ccClient;
            TemplateContext tctx = actx.popTemplateContext();
            try {
                ccClient = tctx.getCompositeComponentClient();
            } finally {
                actx.pushTemplateContext(tctx);
            }
    
            while (ccClient instanceof TemplateManager) {
                ccClient = getProtectedTarget(ccClient);
            }
            if (ccClient == null)
                throw new NullPointerException("No cc client.");
    
            // Instead of ccClient.apply(actx, parent, facetName), we'll drop the enclosing <f:facet>
            if (!(ccClient instanceof CompositeComponentResourceTagHandler))
                throw new RuntimeException("ccClient isn't a resource tag handler.");
    
            CompositeComponentResourceTagHandler ccClientHandler = (CompositeComponentResourceTagHandler) ccClient;
            TagHandler facetHandler = getFacetHandler(ctx, ccClientHandler, facetName);
            if (facetHandler != null) {
                TemplateContext itc = actx.popTemplateContext();
                try {
                    // facetHandler.apply(ctx, parent);
                    FaceletHandler facetNextHandler = getNextHandler(facetHandler);
                    facetNextHandler.apply(ctx, parent);
                } finally {
                    actx.pushTemplateContext(itc);
                }
            }
        }
    
        static TemplateClient getProtectedTarget(TemplateClient client) {
            Field _targetField;
            try {
                _targetField = client.getClass().getDeclaredField("_target");
            } catch (NoSuchFieldException e) {
                return null;
            }
            _targetField.setAccessible(true);
            try {
                return (TemplateClient) _targetField.get(client);
            } catch (ReflectiveOperationException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        }
    
        static final Field _facetHandlersMapField;
        static final Field _facetHandlersField;
        static {
            try {
                _facetHandlersMapField = CompositeComponentResourceTagHandler.class.getDeclaredField("_facetHandlersMap");
                _facetHandlersField = CompositeComponentResourceTagHandler.class.getDeclaredField("_facetHandlers");
                _facetHandlersMapField.setAccessible(true);
                _facetHandlersField.setAccessible(true);
            } catch (NoSuchFieldException e) {
                throw new UnexpectedException(e);
            }
        }
    
        static TagHandler getFacetHandler(FaceletContext ctx, CompositeComponentResourceTagHandler client, String facetName) {
            try {
                Map<String, TagHandler> _facetHandlersMap = (Map<String, TagHandler>) _facetHandlersMapField.get(client);
                if (_facetHandlersMap == null) {
                    Map<String, TagHandler> map = new HashMap<String, TagHandler>();
    
                    Collection<FaceletHandler> _facetHandlers = (Collection<FaceletHandler>) _facetHandlersField
                            .get(client);
                    if (_facetHandlers != null) {
                        for (FaceletHandler handler : _facetHandlers) {
                            if (!(handler instanceof TagHandler))
                                throw new UnexpectedException("Facet-handler is not a tag-handler: " + handler);
    
                            String name = null;
                            if (handler instanceof FacetHandler)
                                name = ((FacetHandler) handler).getFacetName(ctx);
                            else if (handler instanceof InsertFacetHandler)
                                name = ((InsertFacetHandler) handler).getFacetName(ctx);
                            else
                                throw new UnexpectedException("Unknown facet type.");
    
                            map.put(name, (TagHandler) handler);
                        }
                    }
    
                    _facetHandlersMap = map;
                    _facetHandlersMapField.set(client, _facetHandlersMap);
                }
                return _facetHandlersMap.get(facetName);
            } catch (ReflectiveOperationException e) {
                throw new RuntimeException(e);
            }
        }
    
        static final Field nextHandlerField;
        static {
            try {
                nextHandlerField = TagHandler.class.getDeclaredField("nextHandler");
                nextHandlerField.setAccessible(true);
            } catch (NoSuchFieldException e) {
                throw new UnexpectedException(e);
            }
        }
    
        static FaceletHandler getNextHandler(TagHandler handler) {
            try {
                return (FaceletHandler) nextHandlerField.get(handler);
            } catch (ReflectiveOperationException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        }
    
    }
    

    Design composite component as a black box, and retarget the facet components, this may sound great, but it won't work, results in duplicated id(s), and other problems.

    You can replace cc:renderFacet by this renderRawFacet, the difference is, if you have naming container in the composite component, the container client ids will prepended to the facet definition components.

    See:

    1. Discussion on insert/renderFacet.
    2. JSF-2.2 won't include improvement on this issue.
    3. How to write your own tag handler.

    Tested under Myfaces-2.1.1.

    0 讨论(0)
提交回复
热议问题