jsfjsf-2ajax-update

Programmatically control which components should be ajax-updated


I have a complex form where the user fills a few fields, and has two options: generate a license file or save the changes. If the user clicks on the generate license file button without saving the changes, I render a small component with an error message asking him to save before generating the license. To display the component with a warning message, I want to use ajax to avoid rendering the whole page just to render the warning component. Of course, if the changes were saved, then the warning message is not required and I redirect the user to another page. I have a change listener on the changeable fields to detect when a change has been made. What I don't know is the conditional execution. The "render with ajax if unsaved OR redirect if saved" part. Here's the logic

if(saved){
  redirect();
}else{
  ajax.renderWarning()
}

--EDIT-- I'm going to add more info because I realized I'm leaving things too open ended. Here's one example of an updateable field.

<h:inputText name="computername3"  value="#{agreement.licenseServerBeans[2].computerId}" valueChangeListener="#{agreement.fieldChange}">
    <rich:placeholder value="Add Computer ID"/>
</h:inputText>

The fieldChange() bean method

public void fieldChange(ValueChangeEvent event) {   
   change = true; //change is a boolean, obviously :P
}

Here's the generate license button jsf

<h:commandLink action="#{agreement.generateLicenseFile}">
    <span class="pnx-btn-txt">
        <h:outputText value="Generate License File" escape="false" />
    </span>
</h:commandLink>

Here's the generateLicenseFile() method

public String generateLicenseFile(){
    ....//lots of logic stuff
    return "/licenseGenerated.xhtml?faces-redirect=true";
}

Solution

  • Use PartialViewContext#getRenderIds() to get a mutable collection of client IDs which should be updated on the current ajax request (it's exactly the same as you'd specify in <f:ajax render>, but then in form of absolute client IDs without the : prefix):

    if (saved) {
        return "/licenseGenerated.xhtml?faces-redirect=true";
    }
    else {
        FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add("formId:messageId");
        return null;
    }
    

    Returning null causes it to redisplay the same view. You can even add it as a global faces message and let the ajax command reference the <h:messages> in the render.

    if (saved) {
        return "/licenseGenerated.xhtml?faces-redirect=true";
    }
    else {
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(...));
        return null;
    }
    

    with

    <h:messages id="messages" globalOnly="true" />
    ...
    <f:ajax render="messages" />