执行完命令链接后,是否可以将其删除?

时间:2019-03-06 20:13:09

标签: jsf jsf-2.2

我有一张桌子,用户可以在每一行中单击一个链接,该链接触发书的可用性检查。因此,我有一个commandLink和一个action,它可以工作,但是每次用户单击链接时都会执行此操作。我希望只能使用一次。另外,我不想单击链接后隐藏链接,因为它具有onclick代码,可以隐藏并显示详细信息。执行动作后是否可以从命令链接中删除action

1 个答案:

答案 0 :(得分:0)

Is it possible to use EL conditional operator in action attribute?中涵盖的答案是解决此问题的方法之一。话虽如此,自 JSF 2.2 发行以来,还存在其他替代方案。尽管在JSF中删除action属性是有问题的(可以通过一些技巧实现)–另一个解决方案是将actionListeners与连接到f:event事件的preValidate绑定一起使用。这样,您可以随时选择删除任何连接的actionListener。

这是带有事件侦听器的完整解决方案,该事件侦听器在为视图处理组件之前先对其进行修改。基本上,您可以执行以下操作;

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <title>Dynamic action demo</title>
    </h:head>
    <h:body>
        <h:form>
            <h:dataTable var="row" value="#{removeActionBackingBean.rows}">
                <h:column>#{row.primaryColumn}</h:column>
                <h:column>#{row.hasBeenClicked}</h:column>
                <h:column>
                    <h:commandButton actionListener="#{removeActionBackingBean.onPressed(row)}">
                        <f:attribute name="clicked" value="#{row.hasBeenClicked}"/>
                        <f:event listener="#{removeActionBackingBean.onModify}" type="preValidate" />
                        <f:ajax event="click" render="@form" />
                    </h:commandButton>
                </h:column>
            </h:dataTable>
        </h:form>
    </h:body>
</html>

对于支持bean,这是一个具有完整模型的解决方案(使用Lombok);

@Data
@Named
@ViewScoped
public class RemoveActionBackingBean implements Serializable {
    private List<Row> rows;

    @PostConstruct
    private void init() {
         rows = new ArrayList<>();

         for (int i = 0; i < 10; i++) {
             rows.add(new Row(RandomStringUtils.randomAscii(10)));
         }
    }

    public void onPressed(Row row) {
        row.hasBeenClicked = true;
        System.out.println(String.format("'%s' has been pressed!", row.primaryColumn));
    }

    public void onModify(ComponentSystemEvent event) {
        final boolean isRowClicked = (boolean) event.getComponent().getAttributes().get("clicked");

        if (isRowClicked) {
            for (ActionListener al : ((UICommand) event.getComponent()).getActionListeners()) {
                ((UICommand) event.getComponent()).removeActionListener(al);
            }
        }
    }

    @Data
    @RequiredArgsConstructor
    public class Row {
        private @NonNull String primaryColumn;
        private boolean hasBeenClicked;
    }
}

要查看的关键部分是f:eventonModify()方法绑定。如您所见,我们仅检查某个“行”是否被视为已单击-如果是这种情况,我们将清除组件上当前定义的所有actionListeners。实际上,按下按钮时不会调用actionEvent。

尽管上述解决方案修改了按钮的actionListeners,但是它可以被采用并用于其他类型的组件,并且当您希望根据某些条件修改组件的某些属性时-因此了解此技巧非常有用。