Sort of an odd question and I'd like to NOT give away code if possible, so I'll do my best to explain what is going on.
Basically, I have a commandButton that performs an AJAX action and then updates the entire form that it is inside of.
This form works like such:
<h:form id="tabform">
.....
<p:commandButton update=":tabform" value="Save" ajax="true" onstart="savingDialog.show();" onsuccess="savingDialog.hide();" actionListener="#{bean.saveContent}" /> <!-- styling makes it fixed position -->
.....
<p:editor id="ed1" />
<p:editor id="ed2" />
<p:editor id="ed3" />
<p:editor id="ed4" />
<p:editor id="ed5" />
<p:editor id="ed6" />
</h:form>
When I click the save button, and I am at like editor 5, it will save and then place me in the middle of editor 2. Not focus, but "focus of the browser view" (if that makes sense).
I can confirm it has everything to do with the update on the commandButton. It appears to put me half way in the middle of the tabform after the update.
Is there ANY way around this?
Use the scrollTo method on the RequestContext to scroll to a specific component after any server side action. Obviously this will require you devise a scheme to know beforehand, the component you want to level the page to. Without meaningful code from you, you can start off with the following:
public void saveContent(){
//your implementation here
RequestContext context = RequestContext.getCurrentInstance();
context.scrollTo("tabForm:ed5")
}
Related
I'm working with JSF and PrimeFaces, and I can't handle the following situation:
I have a dialog, and I placed a dataTable on it. In one of the cells of the table I would like to display given data in 3 different ways, and I'd like to switch between them. So far I managed to switch between these rendering types via commandLink, but my problem is that when I click on one of the 3 links, the dialog closes! Can I update the content of the dialog, and be able to keep it open the same time? (I'm updating which render type to use via myMethod)
my commandLink looks like this:
<p:commandLink id="id" update=":myForm:myDialog" ajax="false"
action="#{myBean.myMethod}" oncomplete="dialog.show()">
If i don't use the ajax=false attribute, the method is not called, and I also tried imediate=true, but that's not it either.
You need to define an p:outputPanel inside your dialog and update the outputpanel, not the dialog itself (that's why your dialog closes):
<p:dialog id="myDialog" ...>
<p:outputPanel id="myOutputPanel">
... your dialog content goes here
</p>
</p:dialog>
and change your commandlink
<p:commandLink id="id" update=":myForm:myDialog:myOutputPanel" ajax="true"
action="#{myBean.myMethod}" oncomplete="dialog.show()">
Regarding the oncomplete="dialog.show()" - I'm not entirely sure if you need that. A precise answer can be given if you provide more code regarding your table and code.
I had the same problem, and solution is to update a form instead of dialog. For example:
<p:dialog id="id_dialog" ...>
<h:form id="id_form">
... content
</h>
</p:dialog>
and commandLink:
<p:commandLink update=":id_form" process="#all" ...>
This worked for me!
here is my commandButton:
<p:commandButton value="Foo" update="panel1,panel2"
action="#{fooBean.add()}" />
method fooBean.add() is checking if object i want to add is not already in database - it return true - if it is already in base, false if it is not.
what i want to do is display a success message if fooBean.add() will return false after click on button.
It would be nice if that message would be like ConfirmDialog with OK option to close poped out window. Something like this:
http://www.primefaces.org/showcase/ui/confirmDialog.jsf
Any ideas how to help me?
If I understand you correctly you just want to display a dialog, so that the user acknowledges that the action succeeded. You could simply use a growl, but here is a solution using your approach.
.xhtml
<p:commandButton value="Foo" action="#{fooBean.add()}" />
<p:dialog widgetVar="dialog" modal="true">
<p:commandButton value="Ok" icon="ui-icon-close" oncomplete="dialog.hide()" />
</p:dialog>
fooBean
public void add() {
// do stuff
if(isInDB)
RequestContext.getCurrentInstance().execute("dialog.show()");
}
This opens the dialog after your item has already been found in the database. Nevertheless it may be more convenient for the user if he'd get a more subtle notification, without extra clicks.
I need to trigger an ajax update upon change to a text box, which is a <p:autoComplete> component. I have observed that if the user opts to type the text manually, the event is a change, whereas if the user clicks one of the suggestions for the autocomplete, the event is itemSelect. So I added two <p:ajax> children to the input, each calling the same method and having the same update list, but one having event="change" and the other event="itemSelect".
However, I now discover something odd. For example, while in normal server mode I opened my page and typed "12". The autocomplete offered "1233" and "1234" as suggestions. I clicked "1233" and seemingly nothing happened. I clicked again and everything else filled in.
Repeat this in the debugger with a breakpoint on the event handler, and I can see that after the first click, the value is "12" and on the second click, it becomes "1233".
By switching commenting out the two different <p:ajax> I can see the different consequences. Without the "change" one, the handler is never called if the user selects an autocomplete suggestion, and without the "itemSelect" one, the handler is never called if the user types manually. But with both of them, there are two calls, and I'm sure there will be complaints about the double-click.
Some pseudo-code for those that like, first the xhtml:
<p:autoComplete id="itemId" value="#{myBacker.myBean.itemNumber}"
required="true" completeMethod="#{myBacker.idAutoComplete}">
<p:ajax event="itemSelect" update="beanDetails"
listener="#{myBacker.idChangeEventListener()}" />
<p:ajax event="change" update="beanDetails"
listener="#{myBacker.idChangeEventListener()}" />
</p:autoComplete>
<h:panelGroup id="beanDetails">
<h:panelGroup rendered="#{not empty myBacker.myBean.institutionName}">
<h:outputText value="#{myBacker.myBean.institutionName}" />
<!-- Continues with address, phone, etc.. -->
</h:panelGroup>
</h:panelGroup>
Then the Java backing bean code:
public void idChangeEventListener() {
myBean = myDAO.getDetails(myBean);
// another couple of init-type method calls
}
Give the parent tag a widgetVar attribute, then add this little attribute to the <p:ajax event="change" ...> child tag:
onstart="if(widgetVarName.panel.is(':visible')) return false;"
When the question was written, we were on PrimeFaces version 3.5, if I recall correctly. Since then, we need to update the solution to:
onstart="if(PF('widgetVarName').panel.is(':visible')) return false;"
with thanks to mwalter for pointing out the change.
I would appreciate it if someone can give me some hints about progress bar and ajax back-end processing.
To clarify what I need following are details:
I have a command button to do some processing at the back-end.
I would like to show a progress bar that reach the 100% when the backing bean finishes processing back-end instructions.
I looked over many threads but no luck. Most of them did not show a concrete sample how to do that.
Below is a snippet of my code:
</h:panelGrid>
<p:commandButton id="btn" value="DoSomeAction"
styleClass="ui-priority-primary" update="panel"
onclick="PF('pbAjax').start();PF('startButton1').disable();"
widgetVar="startButton1"
actionListener="#{actionBean.DoSomeAction}" />
<p:progressBar widgetVar="pbAjax" ajax="true"
value="#{progressBean.progress}" labelTemplate="{value}%"
styleClass="animated">
<p:ajax event="complete" listener="#{progressBean.onComplete}"
update="growl" oncomplete="startButton2.enable()" />
</p:progressBar>
</p:panel>
This is the code for the Progress Brean:
#ManagedBean(name="progressBean")
public class ProgressBean implements Serializable {
private Integer progress;
public Integer getProgress() {
if(progress == null)
progress = 0;
else {
progress = progress + (int)(Math.random() * 35);
if(progress > 100)
progress = 100;
}
return progress;
}
public void setProgress(Integer progress) {
this.progress = progress;
}
public void onComplete() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Progress Completed", "Progress Completed"));
}
public void cancel() {
progress = null;
}
}
The result of this code is just an empty progress bar and nothing happen when I click on my button.
Thanks in advance.
It'll be easier if I simply walk you through my sample code since you have two beans and I don't know the interaction between them. You can use it to apply it to yours.
<p:commandButton>
<p:commandButton value="Start" type="button" onclick="pbAjax.start();startButton1.disable();" widgetVar="startButton1" />
Nothing impressive here. You have a commandButton with widgetVar="startButton1". When you click on it, onclick comes in and disables the commandButton. It also signals <p:progressBar> to start via pbAjax.start() (<p:progressBar> has widgetVar = "pbAjax.start()").
<p:progressBar>
<p:progressBar widgetVar="pbAjax" value="#{progressBean.progress}" ajax="true" labelTemplate="{value}%">
<p:ajax event="complete" listener="#{progressBean.onComplete}"
update="growl" oncomplete="startButton1.enable()"/>
</p:progressBar>
<p:progressBar> will simply keep calling #{progressBean.progress} to update the progress. When the progress reaches 100% <p:ajax> kicks in and calls #{progressBean.onComplete}. <p:commandButton> get re-enabled and <p:growl> gets updated. Notice how I'm not using PF(...). To be honest, I'm not sure if it makes a difference, I did not test.
Note
In your <p:progressBar> you have oncomplete="startButton2.enable(). It should be startButton1.enable() since your widgetVar value for your <p:commandButton> is startButton1.
Also, notice that I did not use styleClass="animated". With this, you'll just get the bland looking blue bar. If you want to use it then you need to take some extra steps. Looking at your code, it seems you're taking it straight from the PrimeFaces showcase so I'll also use their assets.
Using styleClass="animated"
First, you're going to create a folder called resources in your webapp folder (Web Pages for Netbeans). Then create a folder called css and add in a stylesheet called style.css. The directory structure will be like this: resources/css/style.css. In style.css you're going to have to define this rule. (Don't worry if this is confusing, I'll have the whole code below).
.animated .ui-progressbar-value {
background-image: url("#{resource['images/pbar-ani.gif']}");
}
Then you're going to create an images folder under resources and place the image
pbar-ani.gif in that folder (resources/images/pbar-ani.gif). Image below.
Make sure you have <h:outputStylesheet name='css/style.css' /> in <h:head> and add styleClass="animated" in <p:progressBar>.
Important!
If you are using PrimeFaces 3.5 like I am the image will just not display (including when you're not using styleClass). If you look closely at Firebug you will see the following error
Uncaught TypeError: Object #<Object> has no method 'easeInOutCirc'
One workaround I found for this is to simply use dummy <p:dialog>.
That's it.
You can get more information about the progressBar through the developer's guide.
In case you're wondering how I knew where to get the image you'll have to download the showcase. You can read this article to find out how to download the showcase.
In my opinion, when you really want to use the showcase code, it's better if you simply download the demo. Often time I'm either not seeing the complete picture or the code in the showcase has some mistakes
Anyway here's the sample code as promised. I'm using the same ProgressBean from the showcase (same as yours). Keep in mind that you will have to come up with the logic with how your object interacts with ProgressBean to update the progress bar.
Summary
<h:head>
<h:outputStylesheet name='css/style.css' />
</h:head>
<h:body>
<h:form >
<p:growl id="growl" />
<h3>Advanced Ajax ProgressBar</h3>
<p:commandButton value="Start" type="button" onclick="pbAjax.start();
startButton1.disable();" widgetVar="startButton1" />
<br /><br />
<p:progressBar widgetVar="pbAjax" value="#{progressBean.progress}" ajax="true" labelTemplate="{value}%" styleClass="animated">
<p:ajax event="complete" listener="#{progressBean.onComplete}"
update="growl" oncomplete="startButton1.enable()"/>
</p:progressBar>
<p:dialog></p:dialog><!-- For PrimeFaces 3.5 -->
</h:form>
</h:body>
and remember your directories
resources/css/style.css
resources/images/pbar-ani.gif
I am trying to update my form on the basis of changes of the spinner
<p:spinner id="spin1" min="1" max="#{editPhoto.max}" size="1"
value="#{editPhoto.page}" validator="#{editPhoto.validator()}"
valueChangeListener="#{editPhoto.refreshForm()}" />
<p:commandButton value="Insert" action="#{editPhoto.insertImage()}" />
<p:commandButton value="Delete" action="#{editPhoto.deleteImage()}" />
I've put break points in the value, setPage as well as in the validator and valueChangeListener and it hits them only when I press the commandButton. I've tried immediate="true", but that adds nothing. What I really want is to know when the value has been changed, but without having to hit the commandButton.
In a previous question BalusC suggested the use of
<f:event type="preRenderView" listener="#{nextpageBacking.onPreRenderView}" />
I suspect that I need something similar here, but what sort of event should I be looking for? Maybe not, so what do I need to do to get changes in the spinner without having to press on the commandButton? Thanks, Ilan
My bean is view-scoped. Perhaps the answer is to use another request scoped-bean and have the request scoped-bean operate on the view-scoped bean? I will try this if this looks like the correct direction.
You should use f:ajax or p:ajax.
The valueChangeListener will only fire when the whole form or the spinner is submitted.
<p:spinner id="spin1" min="1" max="#{editPhoto.max}" size="1"
value="#{editPhoto.page}" validator="#{editPhoto.validator()}">
<p:ajax listener="#{editPhoto.refreshForm()}"
update="#form" process="#this" />
</p:spinner>
The valueChangeListener attribute of the spinner is not the best place to fire your method. You should better put it in the listener attribute of p:ajax. The valueChangeListener should be used if you are interested in the old and the new value.