我有一张桌子,用户可以在每一行中单击一个链接,该链接触发书的可用性检查。因此,我有一个commandLink
和一个action
,它可以工作,但是每次用户单击链接时都会执行此操作。我希望只能使用一次。另外,我不想单击链接后隐藏链接,因为它具有onclick
代码,可以隐藏并显示详细信息。执行动作后是否可以从命令链接中删除action
?
答案 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:event
和onModify()
方法绑定。如您所见,我们仅检查某个“行”是否被视为已单击-如果是这种情况,我们将清除组件上当前定义的所有actionListeners。实际上,按下按钮时不会调用actionEvent。
尽管上述解决方案修改了按钮的actionListeners,但是它可以被采用并用于其他类型的组件,并且当您希望根据某些条件修改组件的某些属性时-因此了解此技巧非常有用。