【问题标题】:update component in another xhtml form from Custom layout p:selectOneRadio not working从自定义布局 p:selectOneRadio 更新另一个 xhtml 表单中的组件不起作用
【发布时间】:2015-08-30 18:59:13
【问题描述】:

我的 xhtml 分为菜单区 (defaultMenu.xhtml) 和内容区 (defaultContent.xhtml)。

defaultMenu.xhtml 的代码是:

<h:form id="defaultmenuform">
    <p:outputPanel id="menupanel" class="contain auto-fixed-center">
        <p:panel id="pmenu" visible="#{phController.user.menuVisible}">
            <table id="stutable">
            <tr>
            <td width="15%">
                <p:outputLabel id="stuname" value="#{phController.phBean.studentName}" />
            </td>
            <td>
                <p:tabMenu activeIndex="#{param.selectedtab}">
                    <p:menuitem value="Home" outcome="phome" icon="ui-icon-star">
                        <f:param name="selectedtab" value="0" />
                    </p:menuitem>
                    <p:menuitem value="Bank" outcome="bhome" icon="ui-icon-person">
                        <f:param name="selectedtab" value="1" />
                    </p:menuitem>
                </p:tabMenu>
            </td>
            </tr>
            </table>
        </p:panel>
    </p:outputPanel>
</h:form>

defaultContent.xhtml 实际上显示了 ph.xhtml 内容(作为功能导航的一部分),代码是:

<ui:define name="content">

<f:event listener="#{phController.readPeople}" type="preRenderView">
</f:event>

<h:form id="form">

<p:selectOneRadio id="selstud" value="#{phController.phBean.ssSeq}" layout="custom">
    <p:ajax update=":defaultmenuform:parentmenupanel :defaultmenuform:stuname" listener="#{phController.onChangePerson}"/>
    <f:selectItems value="#{phController.selectStudents}" />
</p:selectOneRadio>

    <div style="width: 300px; float:left;">
        <p:dataGrid var="studentlist" value="#{phController.listStudent}" columns="1" rowIndexVar="stuindex">
            <p:panel header="" style="text-align:left">
                <h:panelGrid columns="1" style="width:100%">
                    <h:outputText value="#{studentlist.studentName}" />

                    <p:radioButton for=":form:selstud" itemIndex="#{stuindex}"/> Select

                 </h:panelGrid>
            </p:panel>
        </p:dataGrid>
    </div>

    </h:form>
</ui:define>

backing bean的代码是:

    Map<String, Object> studentparam = new HashMap<>();
    studentparam.put("studentSeq", phBean.getSsSeq());

    lS = getBaseDAOService().readStudent("readStudent", studentparam);
    phBean.setStudentName(lS.get(0).getStudentFirstName() + " " + lS.get(0).getStudentLastName());

如您所见,我正在调用 onChangeStu 方法以在 defaultMenu.xhtml 中显示选定的学生姓名。我在 ph.xhtml 和 onClick 中使用自定义布局 p:selectOneRadio 尝试更新 defaultMenu.xhtml 中的 p:outputLabel。

支持 bean 方法被成功调用,并且该值也在变量 phController.phBean.studentName 中设置,但更新不起作用。我还使用查看源进行了检查,id 是“:defaultmenuform:stuname”,我还尝试更新菜单面板“:defaultmenuform:menupanel”,但这些都不起作用。

不知道如何解决这个问题。请提出建议。

包括所有.xhtmls的结构

<h:body id="entirePageBody">
    <div id="page">

        <ui:insert name="header" >
            <ui:include src="/template/defaultHeader.xhtml" />
        </ui:insert>

        <ui:insert name="menu" >
            <ui:include src="/template/defaultMenu.xhtml" />
        </ui:insert>


        <div id="content_div" class="auto-fixed-center">
            <div id="content_div_padding" class="content-block"> 
                <ui:insert name="content" >
                    <ui:include src="/template/defaultContent.xhtml" />
                    <ui:debug hotkey="z" />
                </ui:insert>
        </div>
        </div>

        <ui:insert name="footer" >
            <ui:include src="/template/defaultFooter.xhtml" />
        </ui:insert>

   </div>
</h:body>

PhController.java:

公共类 PhController 扩展 BaseController 实现 Serializable {

private List<Stud> listStudent;
private List selectStudents;
SelectItem option;
private PhBean phBean;
private Boolean menuVisible;

int counter = 0;

public PhController() {

    phBean = new PhBean();
}

public void readPeople() {

    listStudent = new ArrayList<Stud>();
    listStudent.add(new Stud(1, "John Miller"));
    listStudent.add(new Stud(2, "Scott Jackson"));

    selectStudents = new ArrayList();

    option = new SelectItem(listStudent.get(0).getStudentSeq(), "Select");
    selectStudents.add(option);

    option = new SelectItem(listStudent.get(1).getStudentSeq(), "Select");
    selectStudents.add(option);

    phBean.setSsSeq(String.valueOf(1));
    phBean.setSelectedName(listStudent.get(0).getStudentName());

    menuVisible = true;

}

public void onChangePerson() {

    phBean.setSelectedName(listStudent.get(1).getStudentName());
}

// Getters and Setters

}

PhBean.java:

公共类PhBean实现可序列化{

private String ssSeq;
private String studName;    // Used to display the name in the Menu bar.
private String selectedName;

public PhBean() {
}

// Getters and Setters

}

【问题讨论】:

    标签: jsf-2 primefaces


    【解决方案1】:

    我想说的是,在defaultContent.xhtml 中的p:ajax 中,要更新的组件列表应该只用空格分隔,不能用逗号分隔 - 所以尝试改变这个:

    update=":defaultmenuform:menupanel, :defaultmenuform:stuname"
    

    到这里:

    update=":defaultmenuform:menupanel :defaultmenuform:stuname"
    

    更新

    我玩了这个多一点,可能已经找到了线索 - 请将以下代码添加到defaultmenuform

    <p:messages autoUpdate="true" showDetail="true" />
    

    这应该有助于我们跟踪验证失败的原因(如果验证失败是您的根本原因 - 正如我所说,我重现此问题的可能性相当有限)。

    无论如何,当我在 p:selectOneRadio 中选择了某个项目时,出现了这样的错误消息:

    Conversion Error setting value 'test001.Student@4110c95c' for 'null Converter'.
    

    根本原因就在这一行:

    <p:selectOneRadio id="selstud" value="#{phController.phBean.ssSeq}" layout="custom">
    

    p:selectOneRadio 只希望 String 作为 value 传递 - 并且 ssSeq 很可能是不同的类型。尝试更改value 的填充方式,以确保它始终为String - 可能是phBean 的不同属性,或者只是一个全新的String 属性。

    注意:如果这没有帮助,也许您可​​以使用非常简化的示例更新您的问题,说明如果我们要对其进行测试,phControllerphBean 会是什么样子。

    更新 #2

    所以你已经解释了一个问题,你想在每次加载/刷新页面时调用phController.readPeople,但它会随每个 Ajax 请求一起加载,从而覆盖值。

    在您的 PhController(它是一个 bean,对吗?会话范围?)您可以添加类似这样的内容(为了便于阅读,省略了 null 检查):

    public void readPeopleOnGet() {
        FacesContext fc = FacesContext.getCurrentInstance();
        ExternalContext ec = fc.getExternalContext();
        HttpServletRequest req = (HttpServletRequest) ec.getRequest();
        String reqMethod = req.getMethod();
    
        if ("GET".equals(reqMethod)) {
            readPeople();
        }
    }
    

    使用上述方法,您可以保留 defaultContext.xhtml 的这一部分,只要它被实际调用(我假设是这样),只需更改侦听器方法即可:

    <f:event listener="#{phController.readPeopleOnGet}" type="preRenderView">
    </f:event>
    

    对于页面的每个请求仍然会调用 readPeopleOnGet 方法,但是由于 Ajax 请求是 POST,所以它只会在页面加载或刷新时调用 readPeople

    这可能不是一个“完全干净”的解决方案,但在我测试时似乎可以正常工作。

    更新 #3

    好吧,既然您使用 PrimeFaces,那么也可以通过这种方式识别 Ajax 调用:

    public void readPeopleOnGet() {
        RequestContext rc = RequestContext.getCurrentInstance();
    
        if (!rc.isAjaxRequest()) {
            readPeople();
        }
    }
    

    但如果我从最新的 cmets 中得到你的观点,你只想在第一次加载页面时运行 readPeople - 所以下面的部分可能会更好。

    如果PhController 实际上是一个 bean,你没有回答,但我认为它是(你发布的代码中没有可见的注释)。你可以试试@SessionScoped:

    @ManagedBean
    @SessionScoped
    public class PhController extends BaseController implements Serializable {
    // the rest of the PhController goes here...
    

    然后您可以在PhController 中添加类似这样的内容:

    @PostConstruct
    private void init() {
        readPeople();
    }
    

    注解@PostConstruct 确保方法init 在创建bean 后被调用一次。您可以根据需要继续从其他地方调用方法readPeople,同时删除&lt;f:event ... /&gt;readPeopleOnGet,因为它们将不再需要。

    【讨论】:

    • 抱歉没用。我还尝试了 :defaultmenuform:stuname 和 :defaultmenuform:menupanel - 两者都不起作用。为了更清楚起见,如果有助于回答,我还包括了所有 .xhtml 的整体布局。
    • 另一种选择是从两个标识符中删除前导冒号,因为您指的是确切的 ID:update="defaultmenuform:menupanel defaultmenuform:stuname" - 我现在无法真正测试它,但如果这没有帮助,一旦我下班回来,我会试着检查一下。还可以通过检查生成的输出来验证 ID 是否正确。
    • 删除前导冒号也不起作用。引发异常:找不到从“form:selstud”引用的表达式“defaultmenuform:menupanel”的组件。
    • 检查生成的输出,这是 defaultMenu.xhtml 中 p:outputLabel 的行 -
    • 这是 选择
    猜你喜欢
    • 2014-06-19
    • 2017-02-17
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 2019-11-30
    • 1970-01-01
    • 1970-01-01
    • 2012-08-11
    相关资源
    最近更新 更多