是否可以在执行后从commandLink中删除操作?

问题描述 投票:0回答:1

我有一个表,在每一行中,用户可以单击一个触发书籍可用性检查的链接。所以我有一个commandLinkaction,它的工作原理,但每次用户点击链接时都会执行此操作。我希望它只能使用一次。此外,我不想在点击后隐藏链接,因为它有隐藏和显示详细信息的onclick代码。执行操作后是否可以从commandlink中删除action

jsf jsf-2.2
1个回答
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,但它可以被采用并用于其他类型的组件,并且当你想根据某些条件修改组件的某些属性时 - 所以知道这个技巧非常有用。

© www.soinside.com 2019 - 2024. All rights reserved.