在使用 JSF/PrimeFaces 执行 CRUD 操作时,通常需要一种重置托管 bean 字段/属性的通用方法,该方法基本上在一个此类操作成功完成后调用,以便支持 bean 中的字段重置为其初始值(默认) 值(value)。
虚构代码:
@Named
@ViewScoped
public class Bean extends LazyDataModel<Entity> implements Serializable {
@Inject
private Service service; // EJB.
// Holds a list of selected rows in a <p:dataTable>.
private List<Entity> selectedValues; // Getter & setter.
private String someField; // Getter & setter.
// Other fields depending upon the business requirement.
public Bean() {}
@PostConstruct
private void init() {
// Do something.
}
@Override
public List<Entity> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, Object> filters) {
setRowCount(service.rowCount());
// Other complex logic as and when required.
return service.getList(first, pageSize, map, filters); // Returns a List<Entity>.
}
// Resets fields to their default value.
public void reset() {
someField = null;
selectedValues = null;
// Reset other fields to their default value.
}
// Add (insert submitted values to the database).
// This method is basically bound to an action(Listener) of <p:commandButton>.
public void submit() {
if (service.insert(someField)) {
// Add a FacesMessge to indicate a success.
reset(); // Calling reset.
} else {
// Add a FacesMessge to indicate a failure.
}
}
// Update the database using submitted values.
public void onRowEdit(RowEditEvent event) {
if (event.getObject() instanceof Entity) {
Entity entity = (Entity) event.getObject();
Entity newEntity = service.update(entity);
if (newEntity != null) {
// Update the model.
// Other things like adding a FacesMessage to indicate a success.
} else {
// Add a FacesMessage to warn against the null entity returned by the service layer.
}
} else {
// Add a FacesMessage to indicate a failure.
}
reset(); // Finally reset the fields to their initial/default value.
}
// Similarly, performing the delete operation also requires to call the reset() method.
}
submit()
执行“插入”的方法基本上与 JSF/PrimeFaces 命令组件相关联,如 <p/h:commandButton>
或 <p/h:commandLink>
.如。<p:inputText value="#{bean.someField}"/>
<p:commandButton value="Submit"
actionListener="#{bean.submit}"
oncomplete="if(args && !args.validationFailed) {updateTable();}"/>
<!-- Updating a p:dataTable in question after the above p:commandButton completes. -->
<p:remoteCommand name="updateTable" update="dataTable" process="@this"/>
以下与
<p:dataTable>
关联的 AJAX 事件也需要调用reset()
方法。<p:ajax event="rowEdit"
onstart="..."
oncomplete="..."
update="..."
listener="#{bean.onRowEdit}"/>
<p:ajax event="rowEditCancel"
onstart="..."
oncomplete="..."
update="..."
listener="#{bean.reset}"/>
<p:ajax event="page"
onstart="..."
oncomplete="..."
update="..."
listener="#{bean.reset}"/>
<p:ajax event="sort"
onstart="..."
oncomplete="..."
update="..."
listener="#{bean.reset}"/>
<p:ajax event="filter"
onstart="..."
oncomplete="..."
update="..."
listener="#{bean.reset}"/>
可以看出,
reset()
方法需要仔细记住,因为它是从多个地方调用的。这种方式有点难以维护。在每个执行 CRUD 操作的 POST 请求成功完成其工作后,是否存在自动调用这种通用方法的方法?
最佳答案
JSF 对此没有任何标记。
理想情况下,您希望拥有类似 <f:event type="postInvokeAction" listener="#{bean.reset}">
的内容。直接附在<p:dataTable>
.但是 JSF 2.2 中不存在该事件。 OmniFaces 有一个,但仅在 UIViewRoot
上受支持, UIForm
, UIInput
和 UICommand
.
<f:phaseListener>
接近了,但它连接到 UIViewRoot
直接,即使你把它放在 <p:dataTable>
.而且,它需要一个完整的 PhaseListener
执行。
<f:view afterPhase>
似乎是你最好的选择。您只需要对阶段 ID 和源组件进行一些额外的检查。
<p:dataTable binding="#{table}" ...>
<f:view afterPhase="#{bean.reset(table)}" />
<p:ajax ... />
<p:ajax ... />
<p:ajax ... />
<p:ajax ... />
...
</p:dataTable>
public void reset(UIData table) {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() != PhaseId.INVOKE_APPLICATION) {
return;
}
String source = context.getExternalContext().getRequestParameterMap().get("javax.faces.source");
if (!table.getClientId(context).equals(source)) {
return;
}
// Reset logic here.
// ...
}
(
binding
如有必要,可以用硬编码的表客户端 ID 替换)我明白这很尴尬。所以,对于即将到来的 OmniFaces 2.2 我有altered现有的
InvokeActionEventListener
也支持这个用例。它现在支持附加到任何 UIComponent
.<p:dataTable ...>
<f:event type="postInvokeAction" listener="#{bean.reset}" />
<p:ajax ... />
<p:ajax ... />
<p:ajax ... />
<p:ajax ... />
...
</p:dataTable>
public void reset() {
// ...
}
关于jsf - POST(基本上是 Ajaxical)请求完成后调用的潜在方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32057711/