使用composite:insertFacet / renderFacet在t:dataTable中不起作用

时间:2011-10-25 15:24:56

标签: jsf-2 composite-component

我这样做: 资源/ VM / table.xhtml:

...
<composite:interface>
  <composite:facet name="dataBody" required="true"/>
</composite:interface>
...
<composite:implementation>
  <t:dataTable>
    <composite:renderFacet name="dataBody"/>
  </t:dataTable>
</composite:implementation>
...

并在page.xhtml:

...
<vm:table>
  <f:facet name="dataBody">
    <t:column>
      Testing.
    </t:column>
  </f:facet name="dataBody">
</vm:table>
...

问题: 'dataBody'方面未呈现。在JSF1.2中,我曾经用ui执行此操作:insert并且工作正常。

问题: 为什么它不起作用,我应该如何使用模板作为替代?

另见:http://lists.jboss.org/pipermail/jsr-314-open-mirror/2009-September/001526.html

2 个答案:

答案 0 :(得分:3)

解决:我不得不使用insertChildren然后一切正常:)我花了1.5天才发现这个...现在看起来很简单。从RichFaces3.3.3 / JSF1.2迁移到RichFaces4.0 / JSF2是一项很多工作,需要学习很多东西。但我到了那里:)

资源/ VM / table.xhtml:

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

并在page.xhtml:

...
<vm:table>
  <t:column>
    Testing.
  </t:column>
</vm:table>
...

答案 1 :(得分:2)

以下是我自己<cc:insertRawFacet>标记的实现,它的工作方式与ui:insert类似。嗯,这是一个MyFaces解决方案。

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);
        }
    }

}

将复合组件设计为黑盒子,然后重新定位facet组件,这可能听起来不错,但它不起作用,导致重复的id和其他问题。

您可以用cc:renderFacet替换renderRawFacet,区别在于,如果您在复合组件中有命名容器,容器客户端ID将预先添加到构面定义组件。

请参阅:

  1. Discussion on insert/renderFacet.
  2. JSF-2.2 won't include improvement on this issue.
  3. How to write your own tag handler.
  4. 在Myfaces-2.1.1下测试。