【问题标题】:Get list with cc.attrs and ValueExpression on CompositeComponent JSF在 CompositeComponent JSF 上使用 cc.attrs 和 ValueExpression 获取列表
【发布时间】:2014-03-06 16:19:11
【问题描述】:

我应该创建一个复合组件并将其插入到父组件中。我试图在 stackOverflow 上找到我的问题的答案,我发现了这个:

Add programmatically composite component in backing bean

所以,我创建了复合组件:

    <html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://xmlns.jcp.org/jsf/passthrough"
    xmlns:composite="http://java.sun.com/jsf/composite"
    xmlns:ic="http://java.sun.com/jsf/composite/inputComponent">

<composite:interface>
    <composite:attribute name="idPanel" required="true" />
    <composite:attribute name="typeBSPanel" default="default" />
    <composite:attribute name="idPanelHeading" required="true" />
    <composite:attribute name="idPanelBody" required="true" />
    <composite:attribute name="listInputText" required="true"
        shortDescription="Questo componente è un Panel con un numero variabile di InputText di tipo Text, Number e DropDown. Questa lista deve contenere degli oggetti con le seguenti proprietà: label, value e placeholder."></composite:attribute>
    <composite:attribute name="objectBindToPanel" required="true" />
</composite:interface>

<composite:implementation>
    <div class="panel-group" id="accordion">
        <div id="#{cc.attrs.idPanel}"
            class="panel panel-#{cc.attrs.typeBSPanel}">
            <div id="#{cc.attrs.idPanelHeading}" class="panel-heading">
                <button type="button" class="btn btn-#{cc.attrs.typeBSPanel}"
                    data-toggle="collapse" data-target="#collapseBodyPanel">
                    +/-</button>
            </div>
            <div id="collapseBodyPanel" class="panel-collapse collapse in">
                <div id="#{cc.attrs.idPanelBody}" class="panel-body">
                    <ui:repeat var="inputText" value="#{cc.attrs.listInputText}">
                        <ic:inputTextBS preAddon="#{inputText.label}"
                            requiredMessage="This field must not be empty"
                            placeholder="#{inputText.placeholder}"
                            value="#{cc.attrs.objectBindToPanel[inputText.value]}" required="true">
                        </ic:inputTextBS>
                    </ui:repeat>
                </div>
            </div>
        </div>
    </div>
</composite:implementation>

</html>

动态添加复合组件的类和方法:

    public class CCUtility {

    public static void includeCompositeComponent(UIComponent parent, String libraryName, String resourceName, String id, Map<String, String> mapValueExpression) {
        // Prepare.
        FacesContext context = FacesContext.getCurrentInstance();
        Application application = context.getApplication();
        FaceletContext faceletContext = (FaceletContext) context.getAttributes().get("javax.faces.FACELET_CONTEXT");

        // This basically creates <ui:component> based on <composite:interface>.
        Resource resource = application.getResourceHandler().createResource(resourceName, libraryName);
        UIComponent composite = application.createComponent(context, resource);
        composite.setId(id); // Mandatory for the case composite is part of UIForm! Otherwise JSF can't find inputs.

        ExpressionFactory factory = application.getExpressionFactory(); 
        ELContext ctx = context.getELContext(); 
        for (Map.Entry<String, String> entry : mapValueExpression.entrySet()) { 
            ValueExpression expr = factory.createValueExpression(ctx, entry.getValue(), String.class); 
            composite.setValueExpression(entry.getKey(), expr); 
            //composite.getAttributes().put(entry.getKey(), entry.getValue());
            }

        // This basically creates <composite:implementation>.
        UIComponent implementation = application.createComponent(UIPanel.COMPONENT_TYPE);
        implementation.setRendererType("javax.faces.Group");
        composite.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, implementation);

        // Now include the composite component file in the given parent.
        parent.getChildren().add(composite);
        parent.pushComponentToEL(context, composite); // This makes #{cc} available.
        try {
            faceletContext.includeFacelet(implementation, resource.getURL());
        } catch (IOException e) {
            throw new FacesException(e);
        }
    }


}

然后我在另一个类中调用前面的方法,传递我想要的复合组件的属性映射:

public void addPanelHostMachine(){
    this.dataCenterController.getDataCenter().getGroupsHost().add(indexGroupHostMachine, new GroupHost());
    Map<String, String> mapValueExpression = new HashMap<String, String>();
    mapValueExpression.put("idPanel", "panelHostMachine" + indexGroupHostMachine);
    mapValueExpression.put("idPanelHeading", "panelHostMachineHeading" + indexGroupHostMachine);
    mapValueExpression.put("idPanelBody", "panelHostMachineBody" + indexGroupHostMachine);
    mapValueExpression.put("typeBSPanel", "success");
    mapValueExpression.put("listInputText", "#{dataCenterController.dataCenter.groupsHost.get(" + indexGroupHostMachine + ").listOfInputText}");
    mapValueExpression.put("objectbindToPanel", "#{dataCenterController.dataCenter.groupsHost.get(" + indexGroupHostMachine + ")}");
    CCUtility.includeCompositeComponent(panelBodyDataCenter, "panelComponent", "panelComponent.xhtml", "ccPanelHostMachine" + indexGroupHostMachine, mapValueExpression);
    indexGroupHostMachine = indexGroupHostMachine + 1;
}

现在的问题是,当我尝试添加 CompositeComponent 时,我得到了这个错误:

Grave: Servlet.service() for servlet [Faces Servlet] in context with path [/IcaroKBMassiveEditor] threw exception [/resources/panelComponent/panelComponent.xhtml @34,79 preAddon="#{inputText.label}": Property 'label' not found on type java.lang.String] with root cause
javax.el.PropertyNotFoundException: Property 'label' not found on type java.lang.String

我认为这是 EL 表达式和 'composite:attribute' 的问题,但我不知道如何解决。谁能帮帮我?

【问题讨论】:

  • 你解决了吗?你的#{cc.attrs.listInputText} 是哪个类型的?
  • 是的,我做到了。我使用了在我的消息编辑中发布的链接中解释的解决方案。
  • 因为您是新来的,请注意您也可以回答自己的问题。事实上,这就是要走的路。如果您发布问题并稍后找到解决方案,请自己发布答案(在答案部分,问题下方)。否则,问题将无法解决,最好将其删除而不是没有解决方案。
  • 对不起,现在可以了吗?我用答案编辑了我的问题,我不知道我必须用一个新帖子来回答我的问题。
  • 好的,谢谢。在下一个! :-)

标签: el composite-component jsf-2.2


【解决方案1】:

我在这篇文章中找到了解决方案:DataTable Inside Composite Component

代替:

for (Map.Entry<String, String> entry : mapValueExpression.entrySet()) { 
 ValueExpression expr = factory.createValueExpression(ctx, entry.getValue(),String.class); 
  composite.setValueExpression(entry.getKey(), expr); 
        }

我用过:

for (Map.Entry<String, String> entry : mapValueExpression.entrySet()) { 
 ValueExpression expr = factory.createValueExpression(ctx, entry.getValue(),Object.class); 
  composite.setValueExpression(entry.getKey(), expr); 
        }

我在函数调用 factory.createValueExpression 中将 String.Class 替换为 Object.class

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    • 2011-06-06
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    相关资源
    最近更新 更多