动态创建的面板显示在XHTML上但在getViewRoot上缺失

时间:2014-12-07 12:13:07

标签: jsf jsf-2 primefaces jsf-2.2

创建了面板并将其添加到xhtml中,但是当我使用findComponent("-formBotones-wizardEventContainer").getChildren()获取它时,结果为null,因为当真正的html源显示多个子节点时,它的容器有1个子节点(id=tempTextIdLayer)。

我已尝试使用visitTree()的解决方案,但vars target panel 是相同的, wizarEventContainer ,以及只有1个孩子(输入隐藏)

HtmlPanelGroup panel=(HtmlPanelGroup)FacesContextWrapper.getCurrentInstance().getViewRoot().findComponent("formBotones-wizardEventContainer");

    panel.visitTree(VisitContext.createVisitContext(FacesContext.getCurrentInstance()),new VisitCallback() {

        @Override
        public VisitResult visit(VisitContext context, UIComponent target) {
             if (target instanceof HtmlPanelGroup) {
                 HtmlPanelGroup layer = (HtmlPanelGroup) target;
                    System.out.println("id: " + layer.getId()); //wizardEventContainer                  // Collect them in an arraylist orso.
                }

                return VisitResult.ACCEPT;
        }
    });

主要xhtml代码

<h:form id="formBotones" prependId="true">
        <h:panelGroup layout="block" id="wizardEventContainer" styleClass="wizardEventContainer">
            <h:inputHidden id="tempTextIdLayer" value="#{eventProvider.tempTextIdLayer}" />
        </h:panelGroup>
    </h:form>

添加面板时的HTML

<form id="formBotones">
    <input type="hidden" value="formBotones" name="formBotones">

    <div class="wizardEventContainer" id="formBotones-wizardEventContainer">
        <div data-widget="widget_formBotones_text_11_0" id="formBotones-text_11_0">

            <div class="ui-panel-content ui-widget-content" id="formBotones-text_11_0_content">
                <span id="formBotones-editor_text_11_0">Dynamic text</span>
            </div>

            <div class="ui-resizable-handle ui-resizable-e" style="z-index: 90;"></div>
            <div class="ui-resizable-handle ui-resizable-s" style="z-index: 90;"></div>
            <div class="ui-resizable-handle ui-resizable-se ui-icon ui-icon-gripsmall-diagonal-se" style="z-index: 90;"></div>

        </div>

        <input type="hidden" value="text_11_0" name="formBotones-tempTextIdLayer" id="formBotones-tempTextIdLayer">
    </div>

    <input type="hidden" value="e5s4" id="javax.faces.ViewState" name="javax.faces.ViewState">
</form>

创建图层代码

这里,它是一个设置为按钮的actionListener的方法。它创建了一个可调整大小且可拖动的面板,其中包含我将通过javaScript编写动态文本的范围。

    public void createTextLayer() throws IOException{
    logger.entry("EventProvider.createTextLayer()");

    Application app=FacesContextWrapper.getCurrentInstance().getApplication();
    UIComponent parent=FacesContextWrapper.getCurrentInstance().getViewRoot().findComponent("formBotones-wizardEventContainer");
    CommandButton textBtn=(CommandButton)FacesContextWrapper.getCurrentInstance().getViewRoot().findComponent("formControl-textLayerBtn");

    String finalId=null;

    if(tempObjs!=null && tempObjs.size()>0 && tempObjs.containsValue("text")){
        finalId="text_" + space.getIdSpace() + "_" + createFinalIndex("text");
    }
    else{
        finalId="text_" + space.getIdSpace() + "_" + spaceBo.getDao().countSectionPages(space.getIdSpace(),4);
    }


    if(parent!=null){


        HtmlPanelGroup panel=(HtmlPanelGroup)app.createComponent(HtmlPanelGroup.COMPONENT_TYPE);
            panel.setId(finalId);
            panel.setStyleClass(panel.getId());
            panel.setStyle("display:inline-block;min-width:100px;min-height:100px;background:red;overflow:hidden;");
            setTempTextIdLayer(finalId);


        HtmlOutputText text=(HtmlOutputText) app.createComponent(HtmlOutputText.COMPONENT_TYPE);
            text.setId("editor_" + panel.getId());

        panel.getChildren().add(text);


        Resizable resizable=(Resizable)app.createComponent(Resizable.COMPONENT_TYPE);

            resizable.setFor(panel.getId());
            resizable.setMaxWidth(new Integer(800));
            resizable.setMaxHeight(new Integer(600));
            resizable.setMinWidth(new Integer(50));
            resizable.setMinHeight(new Integer(50));
            resizable.setContainment(false);
            resizable.setFor(panel.getId());

            panel.getChildren().add(resizable);         


        Draggable drag=(Draggable)app.createComponent(Draggable.COMPONENT_TYPE);

            drag.setFor(panel.getId());
            drag.setOpacity(new Double(0.6));
            drag.setContainment(new String("parent"));
            drag.setSnap(true);
            drag.setSnapMode(new String("outer"));
            drag.setSnapTolerance(new Integer(5));
            drag.setFor(panel.getId());

            panel.getChildren().add(drag);

        tempObjs.put(panel,"text");
    }

    updateViewRoot();

    //Disabling text button
    textBtn.setDisabled(true);
}

将图层添加到容器代码

这里我获取容器wizardEventContainer,并添加保存在 tempObjs var。

上的每个面板。
public void updateViewRoot(){
    logger.entry("EventProvider.updateViewRoot()");

    UIComponent parent=FacesContextWrapper.getCurrentInstance().getViewRoot().findComponent("formBotones-wizardEventContainer");

    if(parent!=null){
        for (Entry<UIComponent, String> entry : tempObjs.entrySet()) {
            parent.getChildren().add(entry.getKey());
        }
    }
}

1 个答案:

答案 0 :(得分:0)

由于getViewRoot()只返回写在xhtml文件中的元素我决定将动态组件保存在地图中,当我将这个可拖动组件放在正确的站点中时,我会传递css样式和其他属性通过托管bean属性,所以每次在xhtml上添加一个新面板时,我都会创建一个新的动态组件,并设置新的属性,并替换保存在地图中的旧动态组件。

这是一种不优雅的方式,但对我而言目前工作正常。

    public void saveTextLayer(){
    logger.entry("EventProvider.saveTextLayer()");

    List<UIComponent> list=null;

    if(tempObjs.containsValue("text"))
         list=getKeysByValue(tempObjs,"text");

    for (UIComponent c:list){
        if (c instanceof HtmlPanelGroup){
            HtmlPanelGroup panel=(HtmlPanelGroup)c;

            if(panel.getId().equals(getTempTextIdLayer())){
                panel.setStyle(getTempCSS());
                if(panel.getChildren().get(0) instanceof HtmlOutputText){
                    ((HtmlOutputText)panel.getChildren().get(0)).setValue(getTempHTML());
                }

                //Adding delete layer
                Application app=FacesContextWrapper.getCurrentInstance().getApplication();

                HtmlPanelGroup deleteLayer=(HtmlPanelGroup)app.createComponent(HtmlPanelGroup.COMPONENT_TYPE);
                    deleteLayer.setId("delete_" + panel.getId());
                    deleteLayer.setStyle("display:inline-block;width:5px;height:5px;background:white;");
                    deleteLayer.setOnclick("deleteLayer($(this));");
                panel.getChildren().add(0,deleteLayer);

                //Replacing UIComponent
                tempObjs.remove(c);
                tempObjs.put(panel, "text");

                updateViewRoot();

                //Deleting temp vars
                setTempCSS("");
                setTempTextIdLayer("");
                setTempHTML("");
            }
        }
    }