I'm looking to trigger a notification bar on checkbox click using <p:ajax>. The notification bar would have the save option to save data in the database. The update atribute within <p:ajax> doesn't seem to work. It's been quite a research, but couldn't derive at a solution. Am I missing something here ? I'm using JSF 2.1+Primefaces 3.5. Any help would be much appreciated.
xhtml page
<p:column headerText="#{msgs.ref}" styleClass="menuHeader textAlignLeft">
<p:notificationBar widgetVar="customSaveBar" position="top" styleClass="saveBar warningBar textAlignCenter" style="height: 25px;padding-top: 0; padding-bottom: 0;" effect="none" rendered="true">
<h:outputText value="There are pending changes on the page." styleClass="warningText"/>
<h:outputText value=" "/>
<p:commandLink action="#{abcDashboardBean.abcDTOValues}"
onclick="skipPageRedirectWarning = true;showPleaseWait();"
styleClass="warningText" id="saveFromBar"
onsuccess="customSaveBar.hide()"
oncomplete="placeRemoveIcon();"
update="#form"
process="#form"
value="#{msgs.save}"/>
</p:notificationBar>
<p:selectBooleanCheckbox styleClass="margin_left_10" value="#{abcDto.refBl}"
rendered="#{!authorizationBean.userADMIN or !authorizationBean.userPM or !authorizationBean.userINDM}">
<p:ajax event="click" partialSubmit="true" update="customSaveBar"></p:ajax>
</p:selectBooleanCheckbox>
</p:column>
abcDashboardBean.java
public Map<Object, Boolean> getAbcDTOValues(){
Map<Object, Boolean> map = new LinkedHashMap<Object, Boolean>();
//fill the map with the items defaulted to unchecked
for (AbcDTO abcDTO: abcList){
map.put(abcDTO.getPpcCode(), Boolean.FALSE);
}
Abc abc1 = dataAccessEjbService.find(Abc.class, abc.getId());
saveAbcRefChanges(map, abc1);
return map;
}
public void saveAbcRefChanges(Map<Object, Boolean> map, Abc abc) {
for (Map.Entry<Object, Boolean> entry : map.entrySet()) {
if (entry.getValue().equals(true) && abc != null) {
abc.setReferenceBl(true);
} else {
abc.setReferenceBl(false);
}
}
dataAccessEjbService.update(abc);
}
AbcDTO.java
private boolean refBl;
// getters + setters
Related
We have implement the datascroller from primefaces and extend it with lazy=true this works fine for the first lazy loading. But when I scroll down no event is fired from Frontend. The Backend works as expected.
I test it with changing the chunk size and get a better understanding what is happen in the backend code. We override the load function what primefaces is calling when you reach the end of page. I changed the code to not lazyloading by scrolling, therefor i implement a button to load the next chunk when you click the button. But Button disappear after clicking it once.
Xhtml:
<p:dataScroller value="#{stakeholderOverviewController.model}" var="stakeholder" chunkSize="50" lazy="true" rowIndexVar="test">
<f:facet name="header">
Scroll Down to Load More Cars
</f:facet>
<f:facet name="loader">
<p:commandButton type="button" value="More" icon="pi pi-chevron-circle-down"/>
</f:facet>
<h:panelGrid columns="2" style="width:100%" columnClasses="logo,detail">
<p:outputPanel>
<h:panelGrid columns="2" cellpadding="5">
<h:outputText value="Id:" />
<h:outputText value="#{stakeholder.lastname}" style="font-weight: bold"/>
<h:outputText value="Year:" />
<h:outputText value="#{stakeholder.firstname}" style="font-weight: bold"/>
</h:panelGrid>
</p:outputPanel>
</h:panelGrid>
<ui:include rendered="#{empty stakeholder}" src="/WEB-INF/compositions/stakeholderEmptyModel.xhtml" />
</p:dataScroller>
there is the backend code for Controller:
public StakeholderOverviewController() {
model = new LazyDataModel<StakeholderSearchWrapper>() {
#Override
public List<StakeholderSearchWrapper> load(int first, int pageSize, String sortField, SortOrder sortOrder,
Map filters) {
List<StakeholderSearchWrapper> execQuery = execQuery(first, pageSize);
return execQuery;
}
};
model.setRowCount(0);
}
....
protected synchronized List<StakeholderSearchWrapper> execQuery(int first, int pageSize) {
if (tmpfirst != first || tmppageSize != pageSize || reExecQuery) {
reExecQuery = false;
tmpfirst = first;
tmppageSize = pageSize;
tmpModel = new LinkedList<>();
// Query for stakeholder
queryresponse = stakeholderService.findByLastnameOrFirstmanOwnerOrShare(getSearchText(), getClientId(),
first, pageSize, selectedFacets, nameSort[getSort()]);
setFacets(queryresponse.getFacetFields());
Set<String> stakeholderIds = new HashSet<String>();
// convert for view
for (SolrDocument details : queryresponse.getResults()) {
StakeholderSearchWrapper stakeholderSearchWrapper = new StakeholderSearchWrapper(details);
tmpModel.add(stakeholderSearchWrapper);
stakeholderIds.add(stakeholderSearchWrapper.getId());
}
historyCount = stakeholderService.countHistoryEntryByStakeholders(stakeholderIds);
notesCount = stakeholderService.countNoteEntriesByStakeholders(stakeholderIds);
assignedProjects = projectService.findByStakeholderIds(stakeholderIds);
for(StakeholderSearchWrapper dao : tmpModel) {
dao.setHistoryCount(getHistoryCount(dao.getId()));
dao.setNoteCount(getNoteEntriesCount(dao.getId()));
dao.setProjects(getAssignedProjects(dao.getId()));
}
SolrDocumentList result = queryresponse.getResults();
int numFound = (int) result.getNumFound();
return tmpModel;
} else {
return tmpModel;
}
}
What i want is that the lazy loading dont fire only once. It should fire as often as needed. I dont know where i have to set some variable to do this. When im debuging the current code the load function is only requested at the first run of the page refresh and than one lazy loading is called but then nothing happens.
I think I realized the trick. Check the line:
model.setRowCount(0);
Instead, set the model row count properly using the max amount of data you want to display:
int totalNumberOfRegisters = this.count(/* relevant paramenters*/);
model.setRowCount(totalNumberOfRegisters);
I am using p:autoComplete inside column of a data table. And I am setting
converter by using variable assigned to the data table converter="#{fieldVar.possibleValues}"
but, it throws :
converter="#{fieldVar.possibleValues}": java.lang.IllegalArgumentException: Cannot convert userConverter of type class java.lang.String to interface javax.faces.convert.Converter
possibleValues is a string
If this is not possible then how we can change the converter dynamically.
<p:dataTable var="fieldVar" value="#{dynamicReportBean.screenMetadataDTOs}" id="edit_meta_data_datatable">
<p:column headerText="Filter Names">
<h:outputText value="#{fieldVar.filedName}"/>
</p:column>
<p:column headerText="Filter Values">
<p:inputText value ="#{fieldVar.filedValue}"
placeholder="#{fieldVar.filedName}"
rendered="#{dynamicReportBean.canRenderFieldType(fieldVar.fieldId, 'TEXTFIELD')}" style="width: 220px">
</p:inputText>
<p:selectOneMenu value="#{fieldVar.filedValue}"
rendered="#{dynamicReportBean.canRenderFieldType(fieldVar.fieldId, 'DROPDOWN')}" style="width: 220px">
<f:selectItems value="#{dynamicReportBean.retrievePossibleDropDownValues(fieldVar.fieldId, fieldVar.fieldType, fieldVar.possibleValues)}"/>
</p:selectOneMenu>
<p:selectManyMenu value="#{fieldVar.filedValue}"
style="width: 220px"
showCheckbox="true"
rendered="#{dynamicReportBean.canRenderFieldType(fieldVar.fieldId, 'SELECT_MANY_CHECKBOX')}">
<f:selectItems value="#{dynamicReportBean.retrievePossibleDropDownValues(fieldVar.fieldId, fieldVar.fieldType, fieldVar.possibleValues)}"/>
</p:selectManyMenu>
<p:autoComplete value="#{fieldVar.filedValue}"
style="width: 220px"
placeholder="autocomplete"
completeMethod="#{dynamicReportBean.getAutoCompleteMethod}"
rendered="#{dynamicReportBean.canRenderFieldType(fieldVar.fieldId, 'AUTOCOMPLETE')}"
scrollHeight="300"
converter="#{fieldVar.possibleValues}"
size="25">
<f:attribute name="converterName" value="#{fieldVar.possibleValues}" />
<p:ajax event="itemSelect" listener="#{dynamicReportBean.onHandleSelect}"/>
</p:autoComplete>
</p:column>
</p:dataTable>
if I pass converter = "userConverter" It works fine but instead of that I want converter values come dynamically
public class UserConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
UserLOVBean lOVBean = null;
try {
UserService service = new UserServiceImpl();
UserFilterDTO filterDTO = new UserFilterDTO();
UserContext userContext
= (UserContext) context.getExternalContext().getSessionMap().
get("USER_CONTEXT");
filterDTO.setCmpCode(userContext.getCmpCode());
filterDTO.setOrgCode(userContext.getOrgCode());
if (value != null) {
filterDTO.setUserId(value);
}
for (UserLOVDTO lOVDTO : service.retrieveUserForAutoComplete(
filterDTO)) {
if (value.equals(lOVDTO.getUserId())) {
lOVBean = new UserLOVBean();
CopyUtil.copyValues(lOVDTO, lOVBean);
}
}
} catch (Exception ex) {
ex.printStackTrace();
Logger.getLogger(UserConverter.class.getName()).log(Level.SEVERE,
null, ex);
}
return lOVBean;
}
#Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
return String.valueOf(((UserLOVBean) value).getUserId());
}
}
Setting a converter for p:autoComplete (and any other PrimeFaces component) using the converter attribute is documented as:
An EL expression or a literal text that defines a converter for the component. When it's an EL expression, it's resolved to a converter instance. In case it's a static text, it must refer to a converter id.
So, if you want to use an EL expression, it must point to an instance of a converter. In your bean you could simply add:
public UserConverter getUserConverter() {
return new UserConverter();
}
And then, in your XHTML, use:
<p:anyComponent converter="#{myBean.userConverter}"/>
I have data table is filled dynamically with records.I add ajax request on that data table on rowEdit event.
I want on the method that handle rowEdit event in the back bean to check on some criteria and if it true don't edit this row
i am using PF 3.1
thanks
<p:dataTable id="itemDT" var="item" value="#{itemView.items}" selectionMode="multiple"
selection="#{itemView.selectedItems}"
rowKey="#{item.Id}">
<p:ajax event="rowEdit"
listener="#{itemView.onRowEdit}" />
<p:column headerText="Input three">
<h:outputText value="#{item.inpt3}" />
</p:column>
<p:column headerText="Input four">
<h:outputText value="#{item.inpt4}" />
</p:column>
</p:dataTable>
and the back bean
#ManagedBean(name="itemView")
#ViewScoped
public class ItemView{
private ItemModel selectedItems[];
// getters and setters for selectedItems
private List<ItemModel> items;
// getters and setters for items
public void add(){
// add item to i.e database
}
public void insertRecord(){
// add itemModels to items list
}
public void onRowEdit(RowEditEvent event) {
//check if criteria then cancel editing
}
}
I have a xhtml page with several dialogs declared within it
<ui:include src="/pages/dialogs/dialog1.xhtml"></ui:include>
<ui:include src="/pages/dialogs/dialog2.xhtml"></ui:include>
...
Dialogs are dynamic="true" and each dialog has ajaxExceptionHandler
<p:ajaxExceptionHandler update="exceptionDialog" onexception="PF('exceptionDialog').show();" />
<p:dialog widgetVar="exceptionDialog" id="exceptionDialog">...</p:dialog>
When some dialog opens and exception occures after some action nothing happens. ExceptionDialog is not shown.
The problem is that <p:ajaxExceptionHandler> created after dialog is included <ui:include> in the page and it is too early. You need it to be created when dialog shows up so you nead to create it dinamicly in managed bean.
In each dialog do this
Delete <p:ajaxExceptionHandler> tag.
And add
...
<h:panelGroup id="ajaxExceptionHandlerPlaceholder">
</h:panelGroup>
<p:outputLabel id="exceptionMessage" value="#{pfExceptionHandler.message}" style="color: red" />
<script>
createAjaxExceptionHandlerCommand();
</script>
</p:dialog>
In managed bean add this method
public void createAjaxExceptionHandler() {
AjaxExceptionHandler aeh = new AjaxExceptionHandler();
aeh.setType( null );
aeh.setUpdate( "exceptionMessage" );
FacesContext context = FacesContext.getCurrentInstance();
UIViewRoot root = context.getViewRoot();
final UIComponent[] found = new UIComponent[1];
root.visitTree( new FullVisitContext( context ), new VisitCallback() {
#Override
public VisitResult visit( VisitContext context, UIComponent component ) {
if ( component.getId().equals( "ajaxExceptionHandlerPlaceholder" ) ) {
found[0] = component;
return VisitResult.COMPLETE;
}
return VisitResult.ACCEPT;
}
} );
found[0].getChildren().add( aeh );
}
I have issue when trying to make command link from inside p:galleria component
The problem is despite the fact at run time the link value value="Show present #{present.name} #{present.presentId}" contains the correct value of the id as example value="Show present Foo 1" , when pressing the command link it sends the wrong id of the second object every time
<h:form>
<p:galleria value="#{presentBean.allPresentList}" var="present" panelWidth="500" panelHeight="313" showCaption="true">
<f:facet name="content">
<h:commandLink value="Show present #{present.name} #{present.presentId}" action="pretty:present" actionListener="#{presentBean.setPresentObj}">
<f:attribute name="present" value="#{present.presentId}"/>
</h:commandLink>
</f:facet>
</p:galleria>
</h:form>
#ManagedBean(name="presentBean")
#SessionScoped
public class PresentBean implements Serializable{
ArrayList<Present> allUserPresentList = new ArrayList<Present>();
#PostConstruct
private void usersPresent(){
PresentDao presentDao = new PresentDaoImpl();
allPresentList = (ArrayList<Present>) presentDao.findAllPresents();
}
public ArrayList<Present> getAllUserPresentList() {
return allUserPresentList;
}
public void setAllUserPresentList(ArrayList<Present> allUserPresentList) {
this.allUserPresentList = allUserPresentList;
}
private String presentId ;
public String getPresentId() {
return presentId;
}
public void setPresentId(String presentId) {
this.presentId = presentId;
}
public void setPresentObj(ActionEvent ev){
Object presentOb = ev.getComponent().getAttributes().get("present");
if(presentOb != null){
this.presentId = (String) presentOb;
}else{
presentId = null ;
}
}
}
You need to use a setPropertyActionListener instead of <f:attribute name="present" value="#{present.presentId}"/> as the f:attribute tag is only evaluated when the component is created (only once) not when the component generates html based on the iterated rows.
So you'll need to instead use:
<f:setPropertyActionListener target="#{presentBean.presentId}" value="#{present.presentId}" />
That will set the value of the presentId in your managed bean, so in your action method you can just access the presentId itself already without having to work it out.
Alternatively if you're using a later version of JSF (using Servlet 3.0 or above), then you could create a method in the managed bean which takes the presentId or even the present object as a parameter
e.g. in your managed bean:
public void myAction(Present p){
//do whatever you want with the Present object
}
and in your .xhtml:
<h:commandLink value="Show present #{present.name} #{present.presentId}" actionListener="#{presentBean.myAction(present)}">
</h:commandLink>