Partial submit is a notion specific to JSF
AJAX requests that allows us to submit only the specified components instead of
the whole form. By default, a POST AJAX request will submit the whole form (all
inputs), but, if we specify a list of components IDs separated by space as the
value of the execute
attribute then JSF will submit only those components. These are lightweight
requests that will reduce the network traffic, especially in big forms that
doesn't need to be entirely submitted.
So, in JSF
(Mojarra 2.2.9), we can easily exploit this facility as in the below example:
<h:form>
<h:panelGrid columns="2">
Name:<h:inputText id="nameId"
value="#{playerBean.name}"/>
E-mail:<h:inputText id="emailId"
value="#{playerBean.email}"/>
Country
Code:<h:inputText id="ccId"
value="#{playerBean.countrycode}"/>
Website: <h:inputText id="urlId"
value="#{playerBean.weburl}"/>
<h:commandButton
value="Save" action="#{playerBean.save()}">
<f:ajax execute="nameId ccId"
render="@form"/>
</h:commandButton>
</h:panelGrid>
Name: #{playerBean.name} | E-mail:
#{playerBean.email} | Country code: #{playerBean.countrycode} | Website:
#{playerBean.weburl}
<br/>Save method: #{playerBean.invoked}
</h:form>
The PlayerBean
is very simple:
@Named
@SessionScoped
public class
PlayerBean implements Serializable{
private String name;
private String email;
private String weburl;
private String countrycode;
private String invoked =
"not-invoked";
public void save(){
invoked = "invoked";
System.out.println("Name: " +
name);
System.out.println("email: " +
email);
System.out.println("Country code: "
+ countrycode);
System.out.println("Website: " +
weburl);
}
// getters and setters
}
So, we have
four inputs, but the execute="nameId ccId" will instruct JSF to
submit only the components with IDs, nameId and ccId. You can see the effect
in the below figure:
So, only the
name and the country code was submitted, and the save() method was invoked.
This was partial submit at work!
Now, let's
accomplish the same thing using PrimeFaces. For this, we don't need <f:ajax>
anymore, because PrimeFaces comes with a flag attribute named, partialSubmit.
When the value of this attribute is true (default false), PrimeFaces
"activates" partial submit. Further, we need to indicate the list
containing the components IDs separated by space as the value of the process
attribute. Only these components will participate in submit. For example, we
can write the same use case from above via PrimeFaces, as below:
<h:form>
<h:panelGrid columns="2">
Name:<h:inputText id="nameId"
value="#{playerBean.name}"/>
E-mail:<h:inputText id="emailId"
value="#{playerBean.email}"/>
Country Code:<h:inputText
id="ccId" value="#{playerBean.countrycode}"/>
Website: <h:inputText id="urlId"
value="#{playerBean.weburl}"/>
<p:commandButton value="Save" partialSubmit="true"
process="nameId ccId" update="@form"
action="#{playerBean.save()}"/>
</h:panelGrid>
Name: #{playerBean.name} | E-mail:
#{playerBean.email} | Country code: #{playerBean.countrycode} | Website:
#{playerBean.weburl}
<br/>Save method: #{playerBean.invoked}
</h:form>
A quick
test, will reveal the below results:
Notice that
the values were successfully submitted, but the save() method wasn't invoked.
Well, this issue is specific to PrimeFaces, and the solution is pretty simple.
Basically, you need to add the @this in the list of submitted components. Practically,
you will include the ActionSource component itself in the submission, and this
will instruct PrimeFaces to invoke the method associated with the action
attribute of the ActionSource:
...
<p:commandButton value="Save"
partialSubmit="true" process="@this nameId ccId"
update="@form" action="#{playerBean.save()}"/>
...
Now, if we
perform the test again, the save() method will be invoked!
Complete
source code on GitHub.
P.S. Special
thanks to Constantin Alin Marian for the idea of this post.
Niciun comentariu :
Trimiteți un comentariu