jsf - POST(基本上是 Ajaxical)请求完成后调用的潜在方法

标签 jsf primefaces

在使用 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 &amp;&amp; !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 , UIInputUICommand .

<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/

相关文章:

java - Richfaces、可排序数据表、排序图标

jsf - 如何在 h :form submit 期间将查询参数附加到 POST 请求

javascript - Primefaces:如何更改日历字段按钮上的默认图标?

java - 文本字段验证期间选项卡之间的 jsf 导航

jsf - p :fileUpload uploaded file saved and how do I change it? 在哪里

jsf-2 - 如何重置 primefaces 命令按钮重置类型上的下拉菜单

jsf - Spring Security 4 和 PrimeFaces 5 AJAX 请求处理

html - 如何隐藏h :selectBooleanCheckbox

java - PrimeFaces fileUpload 事件不会触发

java - 如何部分重新加载 ui :repeat?