Conditionally render a p:dataGrid within a p:dialog

UI Components for JSF
Post Reply
cgswtsu78
Posts: 53
Joined: 25 Jan 2011, 19:18

08 Mar 2011, 20:35

Hello,

I'm trying to conditionally hide or show a p:dataGrid based on a session bean property. My p:dataGrid is wrapped in a p:dialog and I thought I could use the p:dialog's closeListener and onCloseUpdate attributes to control the hide/show of the p:dataGrid. I'm using a session based bean boolean property in the rendered attribute of the p:dataGrid that gets set to true in my p:remoteCommand's actionListener="#{bookmarklet.loadImages}" method and then set to false in the closeListener="#{bookmarklet.close}". It never gets rendered even though the loadImages method gets executed and the boolean property is set to true. Ideally, I would like to render the p:dataGrid if the value="#{bookmarkletBean.imageURLs}" is empty. I tried rendered="#{!empty bookmarkletBean.imageURLs}" but I get an EL exception

page:

Code: Select all

<p:dialog header="#{bundle['bookmarklet.dialog.HEADER']}" widgetVar="scrapeDlg" 
                modal="true" height="450" width="700" draggable="false" resizable="false"
                closeListener="#{bookmarklet.close}" onCloseUpdate="imageGrid">    
            <h:form id="scrapeFrm">
                <p:commandButton onclick="rcTest()" value="call server"/>
                <h:inputHidden id="scrapeURL" value="http://www.freefoto.com/preview/04-01-70?ffid=04-01-70"/>
                <p:remoteCommand name="rcTest" process="@this,scrapeURL" actionListener="#{bookmarklet.loadImages}" update="imageGrid"/>
                    <p:dataGrid id="imageGrid" var="img" value="#{bookmarkletBean.imageURLs}" columns="1"  
                                rows="1" paginator="true" effect="true" 
                                paginatorTemplate="{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} " 
                                paginatorPosition="bottom"
                                rendered="#{bookmarkletBean.shouldRender}"> 
                        <p:column>  
                            <h:panelGrid columns="1" style="width:100%">  
                                    <p:graphicImage value="#{img}" width="100" height="100"/>   
                            </h:panelGrid>  
                        </p:column>  
                    </p:dataGrid>
            </h:form>
        </p:dialog>
session bean:

Code: Select all

@Named
@Scope("session") public class BookmarkletBean extends BaseSessionBean{ private List imageURLs; private boolean shouldRender; private String hidden;

public String getHidden() {
    return hidden;
}

public void setHidden(String hidden) {
    this.hidden = hidden;
}

public List<String> getImageURLs() {
    return imageURLs;
}

public void setImageURLs(List<String> imageURLs) {
    this.imageURLs = imageURLs;
}

public boolean isShouldRender() {
    return shouldRender;
}

public void setShouldRender(boolean shouldRender) {
    this.shouldRender = shouldRender;
}
action class:

Code: Select all

@Named
@Scope("request") public class Bookmarklet extends BaseAction{ @Inject private BookmarkletBean bookmarkletBean; @Inject private BookmarkletService bookmarkletService;

public void loadImages(ActionEvent e) throws MalformedURLException, IOException {
    ExternalContext context = FacesUtils.getExternalContext();
    String scrapeURL = context.getRequestParameterMap().get("scrapeFrm:scrapeURL");
    bookmarkletBean.setImageURLs(bookmarkletService.scrape(scrapeURL));
    bookmarkletBean.setShouldRender(true);
}

public void close(CloseEvent e){
    bookmarkletBean.setShouldRender(false);
}

callahan
Posts: 768
Joined: 27 May 2010, 22:52

09 Mar 2011, 00:23

If something isn't rendered, it can't be updated. So when the dataGrid isn't rendered, it can't be updated. The trick is to wrap the dataGrid within something that is always rendered and update the wrapper instead. For example, an outputPanel as shown here:

Code: Select all

<p:dialog header="#{bundle['bookmarklet.dialog.HEADER']}" widgetVar="scrapeDlg"
                modal="true" height="450" width="700" draggable="false" resizable="false"
                closeListener="#{bookmarklet.close}" onCloseUpdate="imageGrid">   
            <h:form id="scrapeFrm">
                <p:commandButton onclick="rcTest()" value="call server"/>
                <h:inputHidden id="scrapeURL" value="http://www.freefoto.com/preview/04-01-70?ffid=04-01-70"/>
                <p:remoteCommand name="rcTest" process="@this,scrapeURL" actionListener="#{bookmarklet.loadImages}" update="imageGridWrapper"/>
                  <p:outputPanel id="imageGridWrapper">
                    <p:dataGrid id="imageGrid" var="img" value="#{bookmarkletBean.imageURLs}" columns="1" 
                                rows="1" paginator="true" effect="true"
                                paginatorTemplate="{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} "
                                paginatorPosition="bottom"
                                rendered="#{bookmarkletBean.shouldRender}">
                        <p:column> 
                            <h:panelGrid columns="1" style="width:100%"> 
                                    <p:graphicImage value="#{img}" width="100" height="100"/>   
                            </h:panelGrid> 
                        </p:column> 
                    </p:dataGrid>
                  </p:outputPanel>
            </h:form>
        </p:dialog>

cgswtsu78
Posts: 53
Joined: 25 Jan 2011, 19:18

11 Mar 2011, 04:17

Thanks Callahan, that worked but now I have a new issue that maybe you can help with....

I was able to get it to conditionally render using your suggestion above, but how would I hide the panel again? I tried using the dialog's closeListener="#{bookmarklet.close}" onCloseUpdate="imageGrid" and then in the bookmarklet.close method I set shouldRender to false but when the dialog opens again the panel is already rendered. Any ideas?

callahan
Posts: 768
Joined: 27 May 2010, 22:52

11 Mar 2011, 09:33

Try with onCloseUpdate="imageGridWrapper".

cgswtsu78
Posts: 53
Joined: 25 Jan 2011, 19:18

11 Mar 2011, 22:44

Thanks for the quick reply...I tried that as well. Maybe the problem stems from how I'm opening the below dialog. I'm doing a<p:commandLink value="#{bundle['registered.home.search.TEXT']}" onclick="webSearchDlg.show();"></p:commandLink> in order to show the dialog and I'm wondering if the dialogs properties are cached....is there another way to open the dialog where the JSF lifecycle is fully processed?

Code: Select all

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:p="http://primefaces.prime.com.tr/ui"
	xmlns:dc="http://dc.dreamcatcher.com/facelet-taglib">
<ui:component>
	<p:dialog header="#{bundle['dreamSearch.HEADER']}"
		widgetVar="webSearchDlg" modal="true" styleClass="dialog dialog2"
		draggable="false" resizable="false" showEffect="fade"
		hideEffect="fade" closeListener="#{dreamSearch.close}" onCloseUpdate="searchTxtPnl,searchPnl">
		<div class="dialog-top-reg"></div>
		<div class="dialog-middle-reg">
			<div class="close-button">
				<h:form>
					<p:commandButton onclick="webSearchDlg.hide()" />
				</h:form>
			</div>
			<h:form class="dialog-content dialog-content2"
				binding="#{dreamSearch.dreamSearchFrm}">
				<h1 class="dream-search">
					<h:outputText value="#{bundle['dreamSearch.HEADER']}" />
				</h1>
				<p class="dream-search">
					<h:outputText value="#{bundle['dreamSearch.SUBHEADER']}" />
				</p>
				<div class="dream-search-wrap">
					<fieldset>
					<p:outputPanel id="searchTxtPnl">
						<p:inputText id="searchText" value="#{dreamSearchBean.searchText}"/>
					</p:outputPanel>
						<p:commandButton styleClass="form-btn1"
							value="#{bundle['dreamSearch.search.button.TEXT']}" onclick="webImageSearch()"/>
					</fieldset>
				</div>
				<p:remoteCommand name="webImageSearch" process="searchText, @this" actionListener="#{dreamSearch.search}" update="searchPnl"/>
				<p:outputPanel id="searchPnl" styleClass="data-grid-wrap">
					<h:outputText value="#{bundle['dreamSearch.imageResults.TEXT']}" rendered="#{dreamSearchBean.shouldRender}"/>
					<p:dataGrid var="img" value="#{dreamSearchBean.images}" columns="5"
						rows="10" paginator="true" effect="true"
						paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
						rowsPerPageTemplate="10,15,20" paginatorPosition="bottom" rendered="#{dreamSearchBean.shouldRender}">
						<p:column>
							<h:panelGrid columns="1" style="width:100%">
								<p:graphicImage value="#{img}" width="40" height="50" />
							</h:panelGrid>
						</p:column>
					</p:dataGrid>
				</p:outputPanel>
			</h:form>
		</div>
		<div class="dialog-bottom-reg"></div>
	</p:dialog>
</ui:component>
</html>

Code: Select all

package com.dc.web.actions;

import java.util.List;

import javax.faces.component.UIForm;
import javax.faces.event.ActionEvent;
import javax.inject.Inject;
import javax.inject.Named;

import org.primefaces.event.CloseEvent;
import org.springframework.context.annotation.Scope;
import org.springframework.util.StringUtils;

import com.dc.api.model.Dream;
import com.dc.api.service.DreamService;
import com.dc.api.service.ImageSearchService;
import com.dc.web.beans.DreamSearchBean;
import com.dc.web.util.FacesUtils;


@Named
@Scope("request")
public class DreamSearch extends BaseAction {
	@Inject
	DreamService dreamService;
    @Inject
    ImageSearchService flickrSearchImpl;
	@Inject
	private DreamSearchBean dreamSearchBean;
    private UIForm dreamSearchFrm;
    
    
    public void init(){
    	if (!FacesUtils.isPostback()) {
    		dreamSearchBean.setShouldRender(false);
    		dreamSearchBean.setSearchText(null);
    	}
    }

	public void setDreamSearchFrm(UIForm dreamSearchFrm) {
		this.dreamSearchFrm = dreamSearchFrm;
		init();
	}
	
	public void search(ActionEvent e){
		try {
			
			if(dreamSearchBean.getSearchText() != null && !dreamSearchBean.getSearchText().isEmpty()){
				List<String> searchResults = flickrSearchImpl.searchByKeyWord(dreamSearchBean.getSearchText());
				dreamSearchBean.setImages(searchResults);
				dreamSearchBean.setShouldRender(true);
			}else{
				dreamSearchBean.setShouldRender(false);
			}
			
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
	}
	
	public void close(CloseEvent e){
		dreamSearchBean.setShouldRender(false);
		dreamSearchBean.setSearchText(null);
	}

	public UIForm getDreamSearchFrm() {
		return dreamSearchFrm;
	}
}

Code: Select all

package com.dc.web.beans;

import java.util.List;

import javax.inject.Named;

import org.springframework.context.annotation.Scope;


@Named
@Scope("session")
public class DreamSearchBean extends BaseSessionBean {
	private List<String> images;
	private String searchText;
	private boolean shouldRender;
	
	

	public String getSearchText() {
		return searchText;
	}

	public void setSearchText(String searchText) {
		this.searchText = searchText;
	}

	public boolean isShouldRender() {
		return shouldRender;
	}

	public void setShouldRender(boolean shouldRender) {
		this.shouldRender = shouldRender;
	}

	public List<String> getImages() {
		return images;
	}

	public void setImages(List<String> images) {
		this.images = images;
	}

}


callahan
Posts: 768
Joined: 27 May 2010, 22:52

11 Mar 2011, 23:59

Command buttons such as the following are probably doing more than you think. They're sending requests to the Web server that process the view. To avoid this set their type attribute to "button". The requests can be seen with Firebug.

Code: Select all

               <p:commandButton onclick="webSearchDlg.hide()" />
               ...
                  <p:commandButton styleClass="form-btn1"
                     value="#{bundle['dreamSearch.search.button.TEXT']}" onclick="webImageSearch()"/>
The command button and remote command can probably be combined into one.

Code: Select all

                  <p:commandButton styleClass="form-btn1"
                     value="#{bundle['dreamSearch.search.button.TEXT']}" onclick="webImageSearch()"/>
                  ...
            <p:remoteCommand name="webImageSearch" process="searchText, @this" actionListener="#{dreamSearch.search}" update="searchPnl"/>
            
            is the same as:
            
                  <p:commandButton styleClass="form-btn1"
                     value="#{bundle['dreamSearch.search.button.TEXT']}"  process="searchText, @this" actionListener="#{dreamSearch.search}" update="searchPnl"/>

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 61 guests