Primefaces : GraphicImage does not refresh - ajax

I waant to have abutton and a graphicimage. By default, the graphicimage is not displayed. If the user click on the button, the graphic image is displayed (rendered = true).
I can do it but I have to refresh the page to see the graphicimage displayed.
I think I have to use ajax component to make the displaying directly when the button is clicked but I don't manage to use it corectly. Could you guide me?
xhtml :
<h:body>
<h:form>
<p:commandButton value="Prendre la photo générique"
id="boutonPhotoGenerique" icon="ui-icon-image"
action="#{defaultCommandBean.affichePhotoGenerique}">
<p:graphicImage id="photoGenerique"
rendered="#{defaultCommandBean.rendered}"
value="photos/photo_generique.jpg" />
</p:commandButton>
</h:form>
</h:body>
Managed Bean :
#ManagedBean(name = "defaultCommandBean")
#SessionScoped
public class DefaultCommandBean {
private boolean rendered;
public boolean isRendered() {
return rendered;
}
public void setRendered(boolean rendered) {
this.rendered = rendered;
}
public void affichePhotoGenerique() {
rendered = true;
}
}

I found the problem : I surrounded my graphicImage component with a panel component, with id="panel" ; and modified my update attribute to update="panel" . Now, the picture is directy displayed.

Put the graphicImage outside the commandButton and in button declare
update = 'photoGenerique'. Like this:
<h:form>
<p:commandButton value="Prendre la photo générique" update="photoGenerique"
id="boutonPhotoGenerique" icon="ui-icon-image"
actionListener="#{defaultCommandBean.affichePhotoGenerique}">
</p:commandButton>
<p:graphicImage id="photoGenerique"
rendered="#{defaultCommandBean.rendered}"
value="photos/photo_generique.jpg" />
</h:form>

Related

Why does PrimeFaces 5.3 not call my listener function when I catch the "blur" and "focus" events?

My intention was to show information on filling a text area component. When it gets the focus I show the info, when it loses the focus I clear the info. I do not want to proccess any input value just catch the focus and blur events and call the listener and show/clear the message.
I have read BalusC's comment on conditional rendering so I put my conditional text message to an "always rendered" JSF component.
My "always rendered" f:outPutPanel component is shown in the generated XHTML code but my listener function is never called. As far as I know the method signature of primefaces listener is just void somefunction() not like in jsf ajax listener.
I also read BalusC's comment about including #this for the proccess attribute but in my case it seems not to be reasonable as I do not want to catch any input values.
I am newbie to JSF and primefaces so any help is appreciated.
My relevant view snippet:
<h:form>
<h:panelGroup layout="block" id="info">
<h:outputText rendered="#{ebookController.infoMessage != null}" value="#{ebookController.infoMessage}"/>
</h:panelGroup>
....
<p:inputTextarea id="description" styleClass="form-control vspace" required="true" requiredMessage="Kérlek, add meg az e-könyv rövid leírását" value="#{ebookController.newEbook.description}" rows="20" cols="30" counter="display" maxlength="500" counterTemplate="{0} karakter lehet még" autoResize="false" validatorMessage="Az e-könyv leírása maximum 500 karakterből állhat">
<f:validateLength maximum="500"/>
<p:ajax event="focus" process="#none" update="info" listener="#{ebookController.setTextAreaInfoMessage()}"/>
<p:ajax event="blur" process="#none" update="info" listener="#{ebookController.clearInfoMessage()}"/>
</p:inputTextarea>
<h:outputText id="display" />
</h:form>
My relevant java code:
#Named(value = "ebookController")
#SessionScoped
public class EbookController implements Serializable {
private String infoMessage;
public String getInfoMessage() {
return infoMessage;
}
public void setInfoMessage(String infoMessage) {
this.infoMessage = infoMessage;
}
public void setTextAreaInfoMessage(){
setInfoMessage("Tipp: Az e-könyved bemutatása során a fontos részeket emeld ki, és tagold a szöveget bekezdésekkel. Ha egy bekezdés végére értél, csak egy ENTER-t üss!");
}
public void clearInfoMessage(AjaxBehaviorEvent e){
setInfoMessage("");
}
....
}
Solution 1 : User f:ajax
<f:ajax immediate="true" event="focus" process="#none" render="info"
listener="#{ebookController.setTextAreaInfoMessage()}" />
<f:ajax immediate="true" event="blur" process="#none" render="info"
listener="#{ebookController.clearInfoMessage()}" />
Managed Bean
public void setTextAreaInfoMessage() {
System.out.println("setTextAreaInfoMessage");
setInfoMessage(
"Tipp: Az e-könyved bemutatása során a fontos részeket emeld ki, és tagold a szöveget bekezdésekkel. Ha egy bekezdés végére értél, csak egy ENTER-t üss!");
}
public void clearInfoMessage() {
System.out.println("clearInfoMessage");
setInfoMessage("");
}
Reference Problem with h:form and p:ajax

Selection of extendedDataTable inside popupPanel not in Ajax Request Parameter

I am having a JSF page that contains a modal popupPanel from Richfaces and inside this popupPanel is an extendedDataTable. Now I want to have the user selection in my bean every time the user selects a new row. At first I want to show the code then I will explain the problem.
Part of the xhtml page with the popupPanel and the extendedDatatable:
<rich:popupPanel id="kontaktPanel" modal="true" onmaskclick="#{rich:component('kontaktPanel')}.hide()">
<rich:extendedDataTable
value="#{nachfrageBean.loadedKontakte}" var="kontakt"
selection="#{nachfrageBean.selection}" id="kontaktTable">
<rich:column>
<f:facet name="header">
<h:outputText value="#{messages['tabelle.kontakt.instknz']}" />
</f:facet>
<h:outputText value="#{kontakt.instKnz}" />
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="#{messages['tabelle.kontakt.name']}" />
</f:facet>
<h:outputText value="#{kontakt.name}" />
</rich:column>
<a4j:ajax execute="kontaktTable kontaktPanel" event="selectionchange" listener="#{nachfrageBean.selectedRecord}" />
</rich:extendedDataTable>
</rich:popupPanel>
Corresponding bean with the listener and the needed members:
public class NachfrageBean {
private KontaktDTO kontakt;
private List<KontaktDTO> loadedKontakte = new ArrayList<KontaktDTO>();
/** DOCUMENT ME! */
private Collection<Object> selection;
public Collection<Object> getSelection() {
return selection;
}
public void setSelection( Collection<Object> selection ) {
this.selection = selection;
}
public List<KontaktDTO> getLoadedKontakte() {
//contacts are successfully loaded
return kontaktBusiness.getAllKontakte( );
}
public KontaktDTO getKontakt() {
return kontakt;
}
public void setKontakt( KontaktDTO kontakt ) {
this.kontakt = kontakt;
}
public void selectedRecord( AjaxBehaviorEvent event ) {
UIExtendedDataTable dataTable = ( UIExtendedDataTable )event.getComponent();
Object originalKey = dataTable.getRowKey();
for( Object selectionKey : selection ) {
dataTable.setRowKey( selectionKey );
if( dataTable.isRowAvailable() ) {
// do something with the selection
}
}
dataTable.setRowKey( originalKey );
}
}
The listener gets called successfully when the user selects a row in the datatable, but the selection is null, so I am getting a NPE. And when I remove the popupPanel and have my extendedDatatable directly in my page, then it works fine. I am always printing out the request parameters and I can see that there are two missing parameters when I have the datatable inside the pupupPanel. These request parameters are:
mainForm:kontaktTable:wi =
mainForm:kontaktTable:si = 3,3|3||x
So outside the popup the selection from the kontaktTable gets submitted but inside the popupPanel not. Does anyone know whats wrong here?
I just found a solution here .
By default the rich:popupPanel will be attached to the body and not to the form. Adding domElementAttachment="form" to the popupPanel just did it.

Primefaces how to toggle a dashboard widget/panel visibility using ajax?

I have a dashboard with a considerable number of widgets / panels which are working just fine.
I'm looking for a way to toggle the visibility of a specific one using a commandButton ction listener without having to refresh the page, i.e. via AJAX.
<p:dashboard id="board" model="#{dashboardBean.model}">
<!-- iteration code begins -->
<p:panel id="#{wdgt.code}" header="#{wdgt.title}">
<h:outputText value="One of the dozens of widgets" />
</p:panel>
<!-- iteration code ends -->
<p:panel id="staticWdgtId" header="Static Widget Initially Invisible" visible="false">
Some static content
</p:panel>
</p:dashboard>
Then in the backing bean, at some point this action needs to be fired via a commandButton or an actionListener...
public void showTheWidget() {
DashboardColumn dbc = this.model.getColumn(1);
dbc.getWidget(2); // does not get a widget object with a visibility attribute :((
// so that I could manipulate such as dbc.getWidget(2).setVisible(true);
}
Any ideas?
STATIC APPROACH
You can associate the panel with a boolean.
Panel
<p:panel id="staticWdgtId" header="Static Widget Initially Invisible"
visible="#{bean.panelShow}">
Some static content
</p:panel>
Button
<p:commandButton actionListener="#{bean.actionListener()}"
value="Button"
update=":staticWdgtId" />
Bean
public void actionListener() {
setShowPanel(true);
}
DYNAMIC APPROACH
Render all the panel with display: none
Dashboard
<p:dashboard id="board" model="#{dashboardBean.model}">
<p:panel id="#{wdgt.code}" header="#{wdgt.title}" style="display: none">
<h:outputText value="One of the dozens of widgets" />
</p:panel>
</p:dashboard>
remoteCommand
<p:remoteCommand name="panelsToShow"
actionListener="#{bean.panelsToShowAction()}"
oncomplete="handleComplete(xhr, status, args)" />
bean.panelsToShowAction() you need Gson
public void panelsToShowAction() {
List<String> panels = new ArrayList<String>();
//iterate over the panels you want to show, and put #{wdgt.code} which is the id of the panel
panels.add("Code1");//id
panels.add("Code2");//id
RequestContext requestContext = RequestContext.getCurrentInstance();
requestContext.addCallbackParam("panels", new Gson().toJson(panels));
}
JS
$(document).ready(function() {
panelsToShow();
})
function handleComplete(xhr, status, args) {
var panels = eval('(' + args.panels + ')');
for (var i = 0, len = panels.length; i < len; i++) {
$('#'+panels[i]).show();
}
}

Dynamic content inside Ajax's "Update" tag

I am trying to update dynamically the content of the clicked tab inside a tabView in Primefaces. I am trying to simulate what I have inside the listener tag for my ajax, I know this doesn't work when clicking a tab because the EL inside the listener tag has already been evaluated to a string. The question, is there any way to do this?? Thanks for your help.
<p:tabView id="tv1" widgetVar="wv1" activeIndex="1">
<p:ajax event="tabChange"
listener="#{bean.onTabChange}"
update="#{bean.updatedTabID}"/>
<p:tab title="tab1">
<p:dataTable id="dtTab1">... </p:dataTable>
</p:tab>
<p:tab title="tab2">
<p:dataTable id="dtTab2">... </p:dataTable>
</p:tab>
</p:tabView>
Backing bean
String updatedTab
public String updatedTabID(){
return updatedTab;
}
public void onTabChange(TabChangeEvent event) {
Tab activeTab = event.getTab();
String activeTabTitle = activeTab.getTitle();
if(activeTabTitle.equals("tab1")){
updatedTab=":tv1:dtTable1";
// update dataTable1 collection
}else if(activeTabTitle.equals("tab2")){
updatedTab=":tv1:dtTable2";
// update dataTable2 collection
}
}

JSF 2 f:ajax lifecycle problem

The problem is, that if a property is changed during an f:ajax request and a binded panelGroup should be newly created depending on that changed value, the old value is used.
This code will explain the problem.
Here is the backingbean TestBean:
public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
public void setLast(String last) {
this.last = last;
}
public String getName(){
return first+" "+last;
}
public void setDynamicPanel(HtmlPanelGroup panel){ }
public HtmlPanelGroup getDynamicPanel(){
Application app = FacesContext.getCurrentInstance().getApplication();
HtmlPanelGroup component = (HtmlPanelGroup)app.createComponent(HtmlPanelGroup.COMPONENT_TYPE);
HtmlOutputLabel label1 = (HtmlOutputLabel)app.createComponent(HtmlOutputLabel.COMPONENT_TYPE);
label1.setValue(" --> "+getFirst()+" "+getLast());
component.getChildren().add(label1);
return component;
}
and now the jsf/facelet code:
<h:form id="form">
<h:panelGrid columns="1">
<h:inputText id="first" value="#{testBean.first}" />
<h:inputText id="last" value="#{testBean.last}" />
<h:commandButton value="Show">
<f:ajax execute="first last" render="name dyn" />
</h:commandButton>
</h:panelGrid>
<h:outputText id="name" value="#{testBean.name}" />
<h:panelGroup id="dyn" binding="#{testBean.dynamicPanel}" />
</h:form>
After the page was initially loaded the outputText and panelGroup shows both "null" as first and last. But after the button is pressed, the outputText is updated well, but the the panelgroup shows again only "null". This is due to the problem, that the "binded method" dynamicPanel is executed before the update of the first and last properties.
how can workaround this behaviour or what is wrong with my code?
If you add the attribute immediate="true" to your input elements, the values will be applied during the "Apply Request Values" phase, and hence be present before your action executes. You may or may not need the immediate attribute set to true on the commandButton as well.

Resources