一旦将其包装在< h:panelGroup呈现的>中,h:commandButton将无法正常工作. [英] h:commandButton is not working once I wrap it in a <h:panelGroup rendered>

查看:121
本文介绍了一旦将其包装在< h:panelGroup呈现的>中,h:commandButton将无法正常工作.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该主题具有种类"的原因是因为我在JSF 2.2中有一个示例,在该示例中,我使用commandButton并两次调用bean函数(取决于url).基本上是相同的代码,仅在一个示例中执行.

The reason why the topic has "kind of" is because I have an example in JSF 2.2 where I use a commandButton and call a bean function twice (depending on the url). It's basically the same code, which executes only in one example.

以下是在代码下方带有错误"描述的代码:

Here's the code with the description of the "error" below the code:

用户bean

@ManagedBean
@RequestScoped
public class User {

private String name;
private String surname;
private int age;
private int id;

public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}

public String getSurname() {
    return surname;
}
public void setSurname(String surname) {
    this.surname = surname;
}

public int getAge() {
    return age;
}
public void setAge(int age) {
    this.age = age;
}

public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}

public User(String name, String surname, int age, int id) {
    super();
    this.name = name;
    this.surname = surname;
    this.age = age;
    this.id = id;
}

public User(){}

}

UsersBean bean:

UsersBean bean:

@ManagedBean
@SessionScoped
public class UsersBean {

private List<User> listOfUsers = new ArrayList<User>();
private String passedParameter;

public UsersBean() {
    listOfUsers.add(new User("Tywin", "Lannister", 60, 1));
    listOfUsers.add(new User("Tyrion", "Lannister", 30, 2));
    listOfUsers.add(new User("Jaime", "Lannister", 31, 3));
    listOfUsers.add(new User("Cercei", "Lannister", 29, 4));
    listOfUsers.add(new User("John", "Snow", 31, 5));
}

public List<User> getAll() {

    System.out.println("getAall is called.");
    return listOfUsers;
}

public User getDetails() {
    passedParameter = (String) FacesContext.getCurrentInstance()
            .getExternalContext().getRequestParameterMap().get("userID");
    int id = Integer.parseInt(passedParameter);
    User selected = null;
    for (User u : listOfUsers) {
        if (u.getId() == id) {
            selected = u;
        }
    }
    return selected;
}

public String addUser(User u) {
    System.out.println("addUser is called.");
    if (u.getId() != 0) {
        for (User edit : listOfUsers) {
            if (edit.getId() == u.getId()) {
                System.out.println("Found it!");
                edit.setAge(u.getAge());
                edit.setName(u.getName());
                edit.setSurname(u.getSurname());
            }
        }

    } else {
        u.setId(listOfUsers.size() + 1);
        listOfUsers.add(u);
    }

    return "";
}
}

users.xhtml:

users.xhtml:

    <f:view>
        <!-- http://stackoverflow.com/questions/8083469/method-must-have-signature-string-method-etc-but-has-signature-void -->
        <h:dataTable value="#{usersBean.all}" var="u">

            <h:column>
                <f:facet name="header">
                    User ID
                </f:facet>
                    #{u.id}
            </h:column>

            <h:column>
                <f:facet name="header">
                    Name
                </f:facet>
                    #{u.name}
            </h:column> 

            <h:column>
                <f:facet name="header">
                    Details
                </f:facet>

                <h:link outcome="users" value="edit user">
                    <f:param name="userID" value="#{u.id}"></f:param>
                    <f:param name="action" value="edit"></f:param>
                </h:link>

                &nbsp;

                <h:link outcome="usersDetails" value="get details">
                    <f:param name="userID" value="#{u.id}"></f:param>
                </h:link>                   
            </h:column> 

        </h:dataTable>

        <h:panelGroup rendered="#{param['action'] == 'edit'}">
            <h1>Edit!</h1>
            <h:form>
                <ui:param name="editUser" value="#{usersBean.details}"></ui:param>
                <h:outputText value="Name"></h:outputText>
                <h:inputText value="#{editUser.name}"></h:inputText> <br />

                <h:outputText value="Surname"></h:outputText>
                <h:inputText value="#{editUser.surname}"></h:inputText> <br />

                <h:outputText value="Age"></h:outputText>
                <h:inputText value="#{editUser.age}"></h:inputText> <br />

                <h:commandButton action="#{usersBean.addUser(editUser)}" value="Edit" type="submit">    </h:commandButton>
            </h:form>
    </h:panelGroup>

        <h:panelGroup rendered="#{empty param['action']}">
            <h1>Add!</h1>
            <h:form>
                <h:outputText value="Name"></h:outputText>
                <h:inputText value="#{user.name}"></h:inputText>
                <h:outputText value="Surname"></h:outputText>
                <h:inputText value="#{user.surname}"></h:inputText>
                <h:outputText value="Age"></h:outputText>
                <h:inputText value="#{user.age}"></h:inputText>
                <h:commandButton action="#{usersBean.addUser(user)}" value="Add" type="submit"></h:commandButton>
            </h:form>
        </h:panelGroup>     

    </f:view>

好的,所以一切正常. usersBean.addUser添加用户.如果为ID添加另一个inputText并放入现有ID,则相应的函数将更新这些值.因此,addUser函数可以按预期工作.

OK, so, everything works perfectly. usersBean.addUser adds the user. If I add another inputText for ID and I put in an existing ID, the corresponding function updates the values. So, addUser function works as expected.

问题是在

<h:panelGroup rendered="#{param['action'] == 'edit'}">

正如您在上面的xhtml中看到的那样,代码基本相同,唯一的例外是我填写了所选用户的数据.这可行,我将适当的数据输入到输入字段中,但是当我更改它们并单击编辑"时,什么也没有发生.该函数未调用!而在添加的情况下,该函数将被调用并起作用. 似乎在编辑时未定义任何操作,它仅重新加载页面(提交),而没有实际操作addUser.

as you can see in the xhtml above, the code is basically the same, with the sole exception that I fill in the data of the user that was selected. This works, I get the appropriate data into input fields, but when I change them and click Edit, nothing happens. The function is not called! whereas in case of add, the function is called and it works. It appears as if there is no action defined in case of edit, it only reloads the page (submit) without the actual action addUser.

这是怎么引起的,我该如何解决?

How is this caused and how can I solve it?

推荐答案

这是因为#{param['action'] == 'edit'}在处理表单提交过程中未评估true,因此在处理表单提交过程中基本上不呈现<h:panelGroup>,包括坐在其中的<h:commandButton>.表单提交即没有将该参数传递回JSF.这样,JSF将看不到<h:commandButton>,因此将永远无法对其动作事件进行解码和排队.您需要确保在处理表单提交时,所有rendered条件的评估结果都与显示表单时的评估结果相同(这是JSF防范篡改/被入侵请求的保护措施的一部分,否则最终用户将能够执行未提交的命令按钮,例如仅管理员按钮).

It's because #{param['action'] == 'edit'} didn't evaluate true during processing the form submit and therefore the <h:panelGroup> is basically not rendered during processing the form submit, including the <h:commandButton> sitting in there. The form submit namely did not pass that parameter back to JSF. This way JSF won't see the <h:commandButton> and therefore never be able to decode and queue its action event. You need to make sure that all your rendered conditions evaluate the same during processing the form submit as they were during displaying the form (this is part of JSF's safeguard against tampered/hacked requests wherein the enduser would otherwise be able to execute unrendered command buttons like admin-only buttons).

因此,您基本上也需要在回发期间保留该参数,以使rendered表达式在处理表单提交期间仍对true求值.这可以通过几种方式实现:

So, you basically need to retain that parameter during the postbacks as well so that the rendered expression still evaluates true during processing the form submit. This can be achieved in several ways:

  1. 在相关性<h:commandButton>内将其添加为<f:param>:

<h:commandButton action="#{usersBean.addUser(editUser)}" value="Edit" type="submit">
    <f:param name="action" value="#{param.action}" />
</h:commandButton>

(注意:param['action']param.action是等效的;仅当'action'包含句点或表示另一个变量时,这些括号才有用)

(note: param['action'] and param.action are equivalent; those brackets are only useful if the 'action' contains periods, or represents another variable)

通过<f:viewParam>将其设置为bean属性.要求是bean必须在视野范围或更广的范围内.您已经在会话范围中拥有了它,这是可以的(但它是IMO太宽泛了,但除了):

Set it as a bean property by <f:viewParam>. Requirement is that the bean needs to be in view scope or broader. You've it in the session scope already, which is okay (but which is IMO way too broad, but that aside):

<f:metadata>
    <f:viewParam name="action" value="#{usersBean.action}" />
</f:metadata>
...
<h:panelGroup rendered="#{usersBean.action}">
    ...
</h:panelGroup>

  • 如果您已经在使用JSF实用程序库 OmniFaces ,请使用其<o:form>而不是,使您可以提交到当前请求URI而不是当前JSF视图ID.这样,GET请求字符串将自动保留,并且您无需像#1一样在所有命令按钮上复制<f:param>粘贴:

  • If you're already using JSF utility library OmniFaces, use its <o:form> instead of <h:form> which enables you submit to the current request URI instead of to the current JSF view ID. This way the GET request string will automagically be retained and you don't need to copypaste <f:param> over all command buttons like as in #1:

    <o:form useRequestURI="true">
        ...
    </o:form>
    

  • 另请参见:

    • commandButton/commandLink/ajax action/listener方法未调用或输入值未更新-点5
    • See also:

      • commandButton/commandLink/ajax action/listener method not invoked or input value not updated - point 5
      • 这篇关于一旦将其包装在&lt; h:panelGroup呈现的&gt;中,h:commandButton将无法正常工作.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆