How to redirect to a page after printing with primefaces Printer? - jsf

I have used the primefaces printer and wanted to redirect to previous page after printing.I used Printer like this:
<p:commandButton value="Print" type="button" title="Print" actionListener="#{currentpage.redirect}">
<f:ajax execute="#this"/>
<p:printer target="printer" />
</p:commandButton>
In redirect method of currentpage bean i deleted the record which works fine but if i try to redirect it to previous page it doesn't do anything.
public void redirect(ActionEvent actionevent) {
/* Deleted the record */
}
Please guide me if i can do this way or anyother way.
Thanks in advance.

There are several misconceptions in your code:
actionListener method can not fire a redirect. That could be done in action
An ajax request cannot fire a redirect. Ajax is meant to work as an asynchronous request to the server and get the desired result to the current view and handle the response to update the view without refreshing the page nor without navigating.
If using Primefaces components, you should work with them for efficiency in your page. For example, <p:commandButton> should work with <p:ajax> rather than <f:ajax>. But in this case, <p:commandButton> already has ajax capabilities built-in, so there's no need to use any of these ajax components.
After knowing this, you know that your design should change to this:
<p:commandButton value="Print" type="button" title="Print"
action="#{currentpage.redirect}" process="#this">
<p:printer target="printer" />
</p:commandButton>
And the method declaration to:
//parameterless
public void redirect() {
/* Deleted the record */
}
PrimeFaces let's you add behavior when the ajax request is complete by usage of oncomplete attribute. This attribute receives the name of a javascript function that will be invoked right when the ajax request finishes without problems. In this method, you can add the logic for your redirection:
<p:commandButton value="Print" type="button" title="Print"
action="#{currentpage.redirect}" process="#this" oncomplete="redirect()">
<p:printer target="printer" />
</p:commandButton>
<script type="text/javascript>
redirect = function() {
window.location.href = '<desired url>';
}
</script>

Related

PrimeFaces p:ajax event=change and p:commandButton action

I am having some trouble with my application. I have a <p:inputText> with a <p:ajax> listener for the change event. I also have a <p:commandButton> on my page. Both the ajax listener and <p:commandButton> work as expected when only attempting to invoke one. The problem occurs when user edits <p:inputText> and while still focused on the field, attempts to press the <p:commandButton> which triggers the change event ajax listener (expected) but the <p:commandButton> is not invoked (not expected).
Here is my code:
<p:inputText id="code"
value="#{myBean.code}" >
<p:ajax event="change"
listener="#{myBean.method1(myBean.code)}"
update="#(form :input:not(button))" />
</p:inputText>
<p:commandButton id="searchButton"
value="Click me"
action="#{myBean.method2(myBean.code)}"
process="#this code"
update="#form"
oncomplete="PF('myDlg').show()" />
I have read this question but the answer didn't seem to solve the issue for me.
I have tried processing the button on the ajax listener and I tried putting the button in a different form and not updating that form from the ajax listener but I can't figure it out. Is what I am trying to do even possible?
Thanks in advance for any help.
If your project is running on JSF 2.2 runtime, you can utilize passthrough attributes from namespace http://xmlns.jcp.org/jsf/passthrough
I had the same issue (button doesnt work on 1st press, on next presses it works) and solved it on following way:
Add namespace to your page
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
Add oninput attribute to p:inputText (no need for p:ajax)
<p:inputText id="code" value="#{myBean.code}" pt:oninput="onTextChanged()"/>
Add p:remoteCommand bellow
<p:remoteCommand delay="300" name="onTextChanged"
actionListener="#{myBean.method1(myBean.code)}"
update="#(form :input:not(button))" />
(Delay is not necessary but it gives better performance if text is typed fast.)
oninput attribute will help your input fields to detect any kind of change event: typing, deleting, copying, pasting, cutting,etc... and via p:remoteCommand to pass them to managed bean.
And you will also solve "button" issue.
Sorry for my english.
I found another workaround for this issue.
Advantage against approved answer - no additional requests to server on user input.
I realized that the problem is that the button onclick handler is not called.
But I noticed that the onmousedown handler is called. So I added an onmousedown handler where I shedule onclick call. In the onclick handler I check if the method has already been called or not. And if it was, I cancel the event. So onclick executes only one time for one button click.
Page markup:
<p:commandButton id="searchButton"
...
onclick="return fixOnclick(event)"
onmousedown="return fixOnmousedown(event)"
</p:commandButton>
Javascript:
fixOnmousedown: function (e) {
const target = $(e.target);
target.data("eventToProcess", null);
setTimeout(function () {
target.trigger("click");
}, 10);
return true;
}
fixOnclick: function (e) {
const target = $(e.target);
if (target.data("eventToProcess") == null) {
target.data("eventToProcess", e);
}
return target.data("eventToProcess") === e;
}

p:commandButton is reloading the page to open dialog

So I have this code:
<h:form id="serviceCustomFormForm">
<p:dialog id="parameterGroupAddDialog" widgetVar="parameterGroupAddDialog" header="#{messages.addParameterGroup}" modal="true" resizable="false">
<p:inputText value="#{serviceCustomFormBean.serviceParameterGroup.name}" styleClass="Wid90" />
<br />
<br />
<p:commandButton value="#{messages.save}" styleClass="Fright BlueButton" update="serviceCustomFormForm" actionListener="#{serviceCustomFormBean.addServiceParameterGroup}" oncomplete="PF('parameterGroupAddDialog').hide()" />
<p:commandButton value="#{messages.cancel}" styleClass="Fright RedButton" oncomplete="PF('parameterGroupAddDialog').hide()"/>
</p:dialog>
<div class="Container100">
<div class="ContainerIndent">
<p:commandButton value="#{messages.addParameterGroup}" icon="fa fa-plus-circle" styleClass="Fright CyanButton FloatNoneOnMobile" oncomplete="PF('parameterGroupAddDialog').show()" />
<div class="EmptyBox10 ShowOnMobile"></div>
</div>
</div>
</h:form>
When the page is first loaded the #PostConstruct method is called.
When I click the commandButton to open the dialog it's called again. And when I press the Cancel button inside the dialog it's called again.
This behavior does not occur in other parts of the application, and I can't see what I am missing here.
Update: As requested, the Bean code is here:
#ManagedBean
#ViewScoped
public final class ServiceCustomFormBean implements Serializable {
private ServiceParameterGroup serviceParameterGroup = new ServiceParameterGroup();
// Other attributes
#PostConstruct
private void init() {
// Reads attributes sent from previous page
}
public void addServiceParameterGroup() {
// Saves the serviceParameterGroup to database
}
// Getters and Setters
}
It's because the Commandbutton submits the form. You can
change to this:
<p:commandButton type="button" ...onclick="PF('parameterGroupAddDialog').hide()"
Type button tells primefaces not to submit the form. If the form isn't submitted oncomplete is never called. So it's onclick.
Try setting the following attributes to your 'Add Service' and 'Cancel' commandButton elements: partialSubmit="true" process="#this".
Code like this:
<commandButton value="#{messages.addParameterGroup}" ... partialSubmit="true" process="#this" ... />
By default, pf commandButtons try to submit the whole form, while in those two cases you just want to call the invoked method without doing a submit. With this, you are saying to primefaces that you don't want to submit it all (partialSubmit=true), and that you just want to process the invocation of the button itself (process=#this). Maybe that is your problem.
As an additional comment, i don't think getting the label values for the buttons from the bean is a good idea (unless you want to intentionally change the labels dynamically), because you will end up doing excessive requests to the bean. Better try using a messages properties file, as described in here http://www.mkyong.com/jsf2/jsf-2-0-and-resource-bundles-example/.
If I remember correctly, you should put your Dialog outside your main form, at the end of your body or use the appendTo="#(body)" param, and then, have another form inside the dialog.
After a long time dealing with this problem, I finally found the reason.
The annotation ViewScoped that I was importing in the backing bean was from the package javax.faces.view.
The correct one is javax.faces.bean.
Thanks for everyone that spend some time trying to help.

How to forward using h:commandButton

I have a view where I have a form with p:commandButton and everything works fine beacuse I'm using forward and that's what I need:
<h:form id="formularioAltas">
// More code
<p:commandButton value="Guardar" action="#{altasBean.agregarRefaccion()}" update="cboAlmacen cboEstado cboCategoria" />
</h:form>
The method agregarRefaccion() is void so does not changes the page, I think a forward takes place after that action because it always has the same url. That is Ok beacuse that is what I need.
In the same view a have another form where I have a problem with h:commandButton.
<h:form id="myForm" enctype="multipart/form-data" prependId="false">
// More code
<h:commandButton id="button" style="background-color: black; color: aliceblue" value="Guardar imagen para #{altasBean.refaccion.idRefaccion}" action="#{altasBean.subirImagen()}" />
</h:form>
The subirImagen() method is void too so I thought a forward would take place after that action... but it doesn't. The page updates and the url changes so that means a redirect did that.
I will always need a forward. No matter if it is a p:commandButton or a h:commandButton.
I think has something to be with PrimeFaces and the differences of p:commandButton with JSF h:commandButton.
So I need a forward in that h:commandButton.
Edit
I always have an url like this blabla/AlmacenGM/
but when h:commandButton goes the url is: blabla/AlmacenGM/faces/altas.xhtml
The url changes. I have tried to return the string "altas" int the method subirImagen() so a forward should take place but it still changing the url.
Any ideas?
There's no forward with p:commandButton. It's actually an ajax request what you're peforming, because it's its default behaviour.
However, the standard JSF h:commandButton performs a forward request, as long as you return a String with the navigation case in your action method. If you see a redirection taking place there, you must be forcing it in your bean side.
See also:
Ajax update and submission using h:commandButton

How can I change a bean property with a button

I'm trying to create a button that once clicked will change a property in a bean.
<h:commandButton type="button" action="#{loginBean.withdraw}" id="thousand" class="buttons" style="top:180px;left:570px;">
<f:setPropertyActionListener target="#{loginBean.withdrawAmount}" value="1000" />
</h:commandButton>
public class LoginBean {
int withdrawAmount;
This method only works when I omit the type="button" from the commandButton, but with the type="button" it doesn't work and I'm not sure why.
I need the type="button" to be there , is there any way to keep it and still make it work ?
There is an error in your facelet snippet:
There is no such attribute as class for <h:commandButton>. Possibly you meant styleClass.
As for the problem you have, you have to:
Either provide a setter method for the withdrawAmount property
public void setWithdrawAmount(int withdrawAmount) {
this.withdrawAmount = withdrawAmount;
}
and your facelet should look like:
<h:commandButton type="submit"
action="#{loginBean.withdraw}"
id="thousand"
styleClass="buttons"
style="top:180px;left:570px;">
<f:setPropertyActionListener target="#{loginBean.withdrawAmount}"
value="1000" />
</h:commandButton>
Or, you can get rid of the <f:setPropertyActionListener> and add a statement the changes the value of the withdrawAmount as a first line of the #{loginBean.withdraw} method.
In this case your facelet snippet should look like:
<h:commandButton type="submit"
action="#{loginBean.withdraw}"
id="thousand"
styleClass="buttons"
style="top:180px;left:570px;" />
and your LoginBean#withdraw() method should start with the statement, that changes the withdrawAmount value:
public String withdraw() {
this.withdrawAmount = 1000;
//the remaining logic.
}
Personally, I would prefer the first option.
More info:
< h:commandButton > tag reference
JSF Core Tag :setPropertyActionListener vs attribute vs param
The type is the entire reason why you're having this issue. I'm posting this answer because the accepted answer doesn't explain why you're experiencing the issue.
<h:commandButton/> is designed to work in 3 modes:
submit: This is the default mode that the button is set to. This mode sends an HTTP POST request to the server that triggers the JSF request processing lifecycle. It's only this mode that enables you to trigger backing bean methods(using the action or actionListener attributes).
button: This mode triggers a GET request in the application. As GET requests go, this mode is mostly suited for navigation, i.e. requesting another view or page. In this mode, there's no easy/straightforward way to execute backing bean code, or trigger the JSF request processing lifecycle. This is your current issue
reset: This mode simply resets the value of all input components within its enclosing <h:form/>
Reference:
JSF2 Command Button VDL
JSF redirect via commandButton
Difference between h:button and h:commandButton

How to create a simple redirect with JSF?

How do I create a simple redirect with jsf?
I tried:
<h:form>
<h:commandButton action="www.google.de" value="go to google" />
</h:form>
But when I click the button, I just stay on the index page. Nothing happens!
What is wrong here?
Is JSF absolutely necessary here? You don't seem to need to submit anything to your side at all. Just use plain HTML.
<form action="http://www.google.de">
<input type="submit" value="Go to Google" />
</form>
Please note that the URL to the external site must include the scheme (the http:// part), otherwise it would just be submitted relative to the current request URI, such as http://example.com/context/www.google.de.
If you really need to submit to your side, e.g. to preprocess and/or log something, then you could use ExternalContext#redirect() in the action method.
<h:form>
<h:commandButton value="Go to Google" action="#{bean.submit}" />
</h:form>
with
public void submit() throws IOException {
// ...
FacesContext.getCurrentInstance().getExternalContext().redirect("http://www.google.de");
}
You can use:
<h:commandButton value="Go to Google" type="button" onclick="window.location.href = 'http://www.google.de';" />
No need for a form.

Resources