I have a Bean which returns "Notes" for different entities.
E.g. I can have Notes for Offers, Customers, Invoice etc.
Instead of creating many beans for the different entities, I want to have one Bean which returns die correct Notes for each entity. I´ve send in my JSF page the two information "entityType" and "objectId" to the bean. With this two parameters, I can filter my datatable in the bean
Currently I have the following code, in this example for "OFFER":
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:pe="http://primefaces.org/ui/extensions"
template="/WEB-INF/layout/portal/template.xhtml"
xmlns:o="http://omnifaces.org/ui"
xmlns:of="http://omnifaces.org/functions">
<ui:define name="head" />
<ui:define name="title">Page</ui:define>
<ui:define name="content">
<p:growl id="growl" showDetail="false" sticky="false" life="3000" />
<div class="ui-g">
<div class="ui-g-12">
<div class="card card-w-title">
<p:tabView id="offerTab" dynamic="true" cache="false"
widgetVar="tabPanel">
<p:tab id="note"
disabled="#{offerEditController.modeOffer eq 'ADD'}">
<f:facet name="title">
<i class="fa fa-sticky-note Fs12 MarRight40"></i>
<h:outputText value=" Notizen" />
</f:facet>
<div class="EmptyBox10"></div>
<p:outputPanel id="notePanel">
<div class="ui-g ui-fluid">
<div class="ui-g-12 ui-lg-5">
<h:form id="noteForm"
rendered="#{noteRequestByObjectController.init('OFFER', offerEditController.offer.id, offerEditController.offer.idHash)}">
<p:dataTable id="noteListDatatable"
value="#{noteRequestByObjectController.lazyModel}"
var="note" widgetVar="noteTable" resizableColumns="false"
multiViewState="false" selectionMode="single"
selection="#{noteRequestByObjectController.selectedNote}"
filteredValue="#{noteRequestByObjectController.filteredNote}"
rows="50" pageLinks="10" paginatorPosition="bottom"
lazy="true" paginator="true" reflow="true"
currentPageReportTemplate="(Eintrag: {startRecord}-{endRecord} von {totalRecords}, Seite: {currentPage} von {totalPages})"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="50,100,200"
paginatorAlwaysVisible="false"
emptyMessage="Kein Eintrag gefunden">
<f:facet name="header">
<p:outputPanel id="functionalityPanel"
style="float:left; margin-top: -3px">
<p:commandButton value="Neu hinzufügen"
styleClass="green-btn White" icon="fa fa-plus-circle"
actionListener="#{noteRequestByObjectController.doCreateNew}"
update=":offerTab:noteForm:noteListDatatable, :offerTab:addNoteForm"
resetValues="true" ajax="true">
</p:commandButton>
</p:outputPanel>
<h:outputText id="overviewText"
value="Übersicht (#{noteRequestByObjectController.numberTotal})" />
<p:tooltip for="overviewText" position="top"
value="Die Gesamtzahl der Filterung" />
</f:facet>
<p:ajax event="rowSelect" ajax="true" immediate="true"
resetValues="true"
listener="#{noteRequestByObjectController.onSelectNote}"
update=":offerTab:noteForm, :offerTab:addNoteForm" />
<p:column sortBy="#{note.createDate}" visible="true">
<f:facet name="header">
<h:outputText value="Create" />
</f:facet>
<h:outputText id="createDateInfo"
style="margin-left: 5px;" value="#{note.createDate}"
styleClass="Fright">
<f:converter converterId="prettyTimeCustomConverter" />
</h:outputText>
</p:column>
</p:dataTable>
</h:form>
</div>
</div>
</p:outputPanel>
<div class="EmptyBox20"></div>
</p:tab>
</p:tabView>
</div>
</div>
</div>
</ui:define>
My Bean:
- Contains the init function and the function for loading the Notes from Database:
#ViewScoped
#Named
public class NoteRequestByObjectController extends LazyDataModel<Note>
implements SelectableDataModel<Note>, Serializable {
private static final long serialVersionUID = 2815796004558360299L;
private final Logger LOGGER = LoggerFactory.getLogger(NoteRequestByObjectController.class);
#EJB
private NoteService noteService;
#Inject
private LoginBean loginBean;
private List<Note> filteredNote;
private List<Note> selectedNoteList = new ArrayList<Note>();
private LazyDataModel<Note> lazyModel;
private List<Note> list;
private Note selectedNote;
private List<Boolean> toogleList;
private List<ObjectForSearchList> searchList = new ArrayList<ObjectForSearchList>();
private int numberTotal = 0;
public enum ModeNote {
EDIT, ADD
};
private ModeNote mode;
private String entityType;
private String visibleType;
private Long objectId;
private String objectIdHash;
private boolean startLoad = false;
/**
* Init
*/
public boolean init(String currentEntityType, Long currentObjectId, String currentObjectIdHash) {
try {
entityType = currentEntityType;
objectId = currentObjectId;
objectIdHash = currentObjectIdHash;
if (objectId == null || objectIdHash == null)
return true;
lazyModel = null;
// SearchList
initSearchList();
findNote();
selectedNote = new Note();
mode = ModeNote.ADD;
startLoad = true;
LOGGER.info("END init");
return true;
}
catch (Exception e) {
LOGGER.error(ExceptionUtils.getFullStackTrace(e));
}
return false;
}
/**
* Die eigentliche Suche
*/
public void findNote() {
LOGGER.info("START findNote");
lazyModel = null;
if (lazyModel == null) {
lazyModel = new LazyDataModel<Note>() {
#Override
public List<Note> load(int startingAt, int maxPerPage, String sortField, SortOrder sortOrder,
Map<String, Object> filters) {
try {
list = noteService.findAllNoteLazyLoading(searchList, startingAt, maxPerPage, sortField,
sortOrder, filters);
numberTotal = noteService.countNoteRowsLazyLoading(searchList);
lazyModel.setRowCount(numberTotal);
} catch (NoteNotFoundException e) {
lazyModel.setRowCount(0);
numberTotal = 0;
} catch (Exception e) {
lazyModel.setRowCount(0);
numberTotal = 0;
}
return list;
}
#Override
public Note getRowData(String rowKey) {
if (list != null && !list.isEmpty())
for (Note note : list) {
String s = "Note [id=" + note.getId() + "]";
if (s.equals(rowKey))
return note;
}
return null;
}
#Override
public Object getRowKey(Note note) {
return note;
}
};
}
}
The code is working and I got for each different Entity and his ID the correct Notes for this object.
But my problem is, if I have a look in the Log. The init() function is calling multiple times.
Is there any possible solution for that scenario to avoid to have many Beans for each Entity (Customer, Offer, Invoice etc. etc.)
Many thanks
You have your init method on the rendered attribute of the form, so every time that JSF evaluates if the form needs to be rendered it calls the init method.
You could put your init method in a viewAction, something like this:
<f:view ....>
<f:metadata>
<f:viewAction action="#{noteRequestByObjectController.init('OFFER', offerEditController.offer.id, offerEditController.offer.idHash)}"/>
</f:metadata>
This question already has answers here:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
(6 answers)
Closed 6 years ago.
i'm trying to implement a research of products.
My view is something like this:
<h:form>
<p:layoutUnit position="center">
<ui:include src="/Desktop/Users/Include/featureCheckbox.xhtml"/>
</p:layoutUnit>
<p:layoutUnit position="south" style="border: 0px">
<p:commandButton value="Search"
actionListener="#{productsController.searchProdByFeatures()}"
oncomplete="listProd.show();"/>
</p:layoutUnit>
</h:form>
<p:panel widgetVar="listProd" >
<ui:include src="/Desktop/Users/Include/productsScroller.xhtml"/>
</p:panel>
this is productsScroller.xhtml
OT: i don't know why i have to use to view more data, simply scroll doesn't work...
<h:form prependId="false">
<p:dataScroller value="#{productsController.items}" var="item" chunkSize="10">
<f:facet name="header">
Scroll Down to Load More Wheelchair
</f:facet>
<h:panelGrid columns="1" style="width:100%" >
<p:outputPanel>
<h:outputText value="#{item.name}" style="font-weight: bold"/>
</p:outputPanel>
</h:panelGrid>
<f:facet name="loader">
<p:commandButton type="button" value="View More" />
</f:facet>
</p:dataScroller>
</h:form>
and this is productsController (#Named and #ViewScoped)
...
private Collection<Product> items;
private Collection<Product> selectedItems;
public Collection<Product> getSelectedItems() {
return selectedItems;
}
public void setSelectedItems(Collection<Product> selectedItems) {
this.selectedItems = selectedItems;
}
public Collection<Product> getItems() {
if (items == null) {
items = this.ejbFacade.findAll();
}
System.out.println(items.size());
return items;
}
public void setItems(Collection<Product> items) {
this.items = items;
}
public void searchProdByFeatures (){
List<Product> items= (List<Product>) getItems();
List<Product> newItems;
Collection<Feature> featuresCollection = featureController.getSelectedItems();
List<Feature> selectedFeatures = new ArrayList<>(featuresCollection);
System.out.println(selectedFeatures.size()); //just for debug
try {
for (Feature selectedFeature : selectedFeatures) {
String msg=(selectedFeature.getName()+" / ");
System.out.println(selectedFeature.getName());
}
newItems=productFacade.findProdByFeatures(selectedFeatures, items);
System.out.println("Searched product are "+newItems.size()); //just for debug
setItems(newItems);
System.out.println("New items are "+getItems().size()); //just for debug
} catch (NotFoundException e) {
setItems(null);
JsfUtil.addErrorMessage(e.getMessage());
}
}
the method searchProdByFeatures() works well but the problem is that the dataScroller won't update...
i know there is something wrong in the view... but what?
or it'll be better to update the view from controller? how?
Edit your code to upadate the dataScroller by adding update="yourIddataScroller"
<p:commandButton value="Search"
actionListener="#{productsController.searchProdByFeatures()}"
oncomplete="listProd.show();" update="yourIddataScroller"/>
I have a p:inputTextarea and I need the value of it while processing the form. It turned out that every time I submit the form I get all the values except the one from the textarea. #{xyzUI.description} is a String object with regular getters and setters.
<ui:composition>
<h:form id="form1">
<p:panel rendered="...">
<p:panel id="formPanel">
<p:panelGrid columns="2" cellpadding="5">
<!-- other form elements -->
<p:outputLabel>Description:</p:outputLabel>
<p:inputTextarea value="#{xyzUI.description}" style="width: 350px;" counter="display" counterTemplate="{0} characters remaining" maxlength="2000" autoResize="true" rows="4" />
<h:panelGroup />
<h:outputText id="display" />
</p:panelGrid>
<p:commandButton rendered="#{not xyzUI.noChange}" action="#{xyzUI.submitForm}" update="formPanel" ajax="true" value="Apply" >
<p:ajax update="formPanel"></p:ajax>
</p:commandButton>
</p:panel>
</p:panel>
</h:form>
<ui:composition>
In my backing bean the value is always "". I don't know what's wrong.
public void submitForm()
{
...
tmp.setDescription(description); // String is always "" while debugging
myList.add(tmp);
RequestContext.getCurrentInstance().update("content");
}
I ran your code locally and discovered the issue. In the command button, remove the p:ajax call.
PrimeFaces command buttons are ajax enabled by default.
So change this:
<p:commandButton rendered="#{not xyzUI.noChange}" action="#{xyzUI.submitForm}" update="formPanel" ajax="true" value="Apply" >
<p:ajax update="formPanel"></p:ajax>
</p:commandButton>
To this:
<p:commandButton rendered="#{not xyzUI.noChange}" action="#{xyzUI.submitForm}" update="formPanel" value="Apply" />
My backing bean for reference
#ManagedBean
#ViewScoped
public class xyzUI implements Serializable{
private static final long serialVersionUID = 6259024062406526022L;
private String description;
private boolean noChange = false;
public xyzUI(){
}
public void submitForm(){
System.out.println(description);
}
public boolean isNoChange() {
return noChange;
}
public void setNoChange(boolean noChange) {
this.noChange = noChange;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
hello I have a commandLink that executes a method in my baking bean, that method calls an ejb that builds a string and place it as an attribute of the bean (with getters and setters), after executing that method should raise a modal dialog to only display the value of that attribute but it does not, I see the method that builds the chain runs but does not lift the dialogue, this is my code:
xhtml:
<ui:composition>
<p:panelGrid columns="3" style="width: 100%" >
<h:form id="headerForm">
<p:column style="width: 15%;height:auto; text-align: center;">
<p:graphicImage value="#{loginBean.url}" style="align:center;"/>
</p:column>
<p:column>
<div align="center">
<h:outputText styleClass="titleHeader" value="#{loginBean.entityName}" />
</div>
</p:column>
<p:column style="width: 15%;height:auto; text-align: center;">
<div align="right">
<h:commandLink onComplete="PF('dlg').show(); return false;" type="button" ajax="false" action="# {xxxxBean.createString}">
<h:outputText value="Contact" />
</h:commandLink>
</div>
</p:column>
</h:form>
</p:panelGrid>
<p:dialog id="dlg" header="Some title here" widgetVar="dlg" modal="true">
<h:outputText value="#{xxxxBean.stringBuild}" />
</p:dialog>
</ui:composition>
Backing bean:
#ManagedBean
#SuppressWarnings("serial")
public class XxxxBean implements Serializable{
private String stringBuild;
private someBeanRemote ejb;
public XxxxBean() {
// TODO Auto-generated constructor stub
try{
ejb = EjbConsumer.getRemoteEjb();
}catch(Exception e){
e.printStackTrace();
}
}
public void createString(){
List<someObject> list = ejb.findAllActiveObjects(Constants.TOP);
String temp = "";
if( list!=null && list.size() > 0 ){
for(int i=0; i < list.size(); i++){
temp += list.get(i).getName() + "<br/>";
}
this.stringBuild= temp;
}
System.out.println(this.stringBuild);
}
public void setStringBuild(String stringBuild) {
this.stringBuild= stringBuild;
}
public String getStringBuild() {
return stringBuild;
}
}
thanks in advance!!!
You are using ajax=false with oncomplete
oncomplete: Client side callback to execute when ajax request is completed.
Change to:
<p:commandLink oncomplete="PF('dlg').show();" action="#{yourBean.youraction}"></p:commandLink>
that is default ajax = true and everything should work
I am not able to update both the output panels after the ajax call of a method in the backing bean.
Code looks like below given sample code
abc.xhtml
<p:outputPanel id="criteriaPanel" rendered="#{myBean.showPanel}">
<h:form id="loginForm">
<ui:include src="login.xhtml" />
<p:commandButton action="#{myBean.login}" value="Login" update="criteriaPanel successPanel" />
</h:form>
</p:outputPanel>
<p:outputPanel id="successPanel" rendered="#{!myBean.showPanel}">
<h:form id="successForm">
<ui:include src="success.xhtml" />
</h:form>
</p:outputPanel>
MyBean.java
public class MyBean {
private boolean showPanel = true;
public void login() {
this.setShowPanel(false);
}
public void setShowPanel(boolean showPanel) {
this.showPanel = showPanel;
}
public boolean isShowPanel() {
return showPanel;
}
}