JSF autocomplete ignoring null values - java

I have a problem regarding jsf autocomplete elements. I want my page to have an autocomplete element and after a user selects a value from the field, another field is automatically created. The maksimum number of autocomplete field is 3, so after the 3rd one, the 4th one is disabled:
<h:outputLabel for="fieldsOfStudy" value="#{amsg.fieldsOfStudy}"/>
<p:outputPanel id="fieldsOfStudy" autoUpdate="true" layout="block">
<ui:repeat value="#{cc.attrs.offer.fieldsOfStudy}" var="studyField" varStatus="status">
<h:panelGroup id="studyField" layout="block">
<h:outputText value="#{amsg.handleGetObject(enumHelper.toMessageKey(studyField))}"/>
<p:commandLink action="#{cc.attrs.offer.removeFieldOfStudy(status.index)}" process="#this"
update="#([id$=fieldsOfStudyAutocomplete])" styleClass="ui-icon ui-icon-close"/>
</h:panelGroup>
</ui:repeat>
</p:outputPanel>
<h:message for="fieldsOfStudy" errorClass="error"/>
<h:panelGroup id="fieldsOfStudyAutocomplete">
<p:autoComplete value="#{offerBean.selectedFieldOfStudy}" dropdown="true" required="#{empty cc.attrs.offer.fieldsOfStudy}"
completeMethod="#{offerBean.completeFieldsOfStudy}" disabled="#{cc.attrs.offer.fieldsOfStudy.size() >= 3}"
itemValue="#{p}" var="p" itemLabel="#{amsg.handleGetObject(enumHelper.toMessageKey(p))}" styleClass="xLargeInput">
<p:ajax event="itemSelect" process="#this" update="#this"/>
</p:autoComplete>
</h:panelGroup>
Everything works good like this, but the problem is that every time a user presses the Save button if the "Field of study" list has 1 selected element from the autocomplete there will be another one in the list with a null value. If there are 2 selected "field of studies" the 3rd one will be also created but ill have a null value. If there are 3 selected "fields of studies", then there wont be any 4th element in the list.
Is there any way I can set the autocomplete to ignore null fields? In other words, if a user doesnt select anything from the autocomplete, how not to pass null values to the DTO?

I found a way. When setting up the value in the bean you can easily put an if statement like this:
public void setSelectedFieldOfStudy(FieldOfStudy selectedFieldOfStudy) {
if (selectedFieldOfStudy != null) {
this.emptyOffer.getFieldsOfStudy().add(selectedFieldOfStudy);
}
}

Related

PrimeFaces filling dataTable with List<Object> inside another List<Object>

UPDATE:
I found that the issue with the dataGrid not looping through a list inside a list was an issue on the XML code side. Now the dataGrid is reading the List and looping through it creating panels based on the name. The issue now seems to be accessing certain properties in this List.
<p:dataGrid value="#{objList.objList2}" var="objList2" columns="1">
<p:panel id="obj2" header="#{objList2.name}" toggleable="true" collapsed="false">
<h:panelGrid columns="2" style="width: 100%" columnClasses="scenario-viewer-leftcolumn,scenario-viewer-rightcolumn">
<h:outputText value="Output Name:" />
<p:inputText value="#{objList2.objType}" styleClass="textBoxStyle"/>
<h:outputText value="Output Bool:" />
<p:selectBooleanCheckbox value="#{objList2.boolVar}"/>
</h:panelGrid>
</p:panel>
</p:dataGrid>
</p:panel>
</p:dataGrid>
When I try to access a variable under objList2 is gives me the error saying The class obj2 does not have a readable property 'objType'. I double checked and it does have this property/variable and it is initialized.
What makes this even more strange is if I use objList2.boolVar in place of objList2.name in the header for each panel, it displays the information fine. This proves that the property exists and is initialized. Why wouldn't this work in inputText?? Any help would be greatly appreciated.
ORIGINAL:
I am working with PrimeFaces and trying to create a xhtml form for my UI. I am trying to dynamically display data from a list into a dataGrid structure. I am able to do this successfully, but I also need to display data from a list inside the first list.
For example:
I have a List under the variable objList which I use for my first dataGrid. I am able to loop through this list and create panels for each object and some other String data per object.
<p:dataGrid value="#{scenarioTree.objList}" var="objList" columns="1">
<p:panel id="obj" header="#{objList.name}" toggleable="true" collapsed="true">
<h:panelGrid columns="2" style="width: 100%" columnClasses="scenario-viewer-leftcolumn,scenario-viewer-rightcolumn">
<h:outputText value="text:" />
<p:inputText value="#{objList.variable}" styleClass="textBoxStyle"/>
<h:outputText value="text2:" />
<p:inputText value="#{objList.variable2}" styleClass="textBoxStyle"/>
</h:panelGrid>
Now I want to be able to create a second dataGrid that refers to objList2 which is inside objList1. Doing this though returns No records found in the UI even though there is a bunch of records there.
<p:dataGrid value="#{objList.objList2}" var="objList2" columns="1">
<p:panel id="obj2" header="#{objList2.name}" toggleable="true" collapsed="false">
</p:panel>
</p:dataGrid>
</p:panel>
</p:dataGrid>
Is this a bug with PrimeFaces or am I not able to do this? Or am I doing this wrong?
whenever we are talking about iterating list in xhtml we have dataTable,dataGrid, etc and panelGrid also becoz dataTable and all others are child of panelGrid(we can say this becoz panelGrid is also going to form table and others as well i meant child from this way) so in this case try to iterate the inner list in panelGrid since you are using panelGrid and referring variable is list so internally jsf is going to understand like this:
objList.get(i).getVariable();//For the first row
but according to your code it is understanding like this:
objList.getVariable();
which is not at all present so it is giving issue take out panel i don't find it's use and use like this:
<p:panelGrid value="#{objList}" var="obj">
//Access properties inside that
</p:panelGrid>
you can use <f:facet> tag if you want something in header

Primefaces datatable cell editing doesn't update

I have a primefaces datatable with cell editing which is toggled on a boolean variable in the view.
I have three issues:
In edit mode, I change a value and I click the save button on the page it doesn't keep the new value, If I click anywhere else first on the page then click save it will keep the value. I need it to keep the value if you click save first.
If I edit a cell which is an input text and I click out the field now is a output text until I click in there again. I want the field to look like a input text while in edit mode.
When the save button is clicked the backing method sets the editable boolean to false, and the rest of the page obeys, and the dataTable looks like it obeyed but if you click a cell it will let you edit it.
Here is the code:
<p:dataTable value="#{view.LineItems}" var="lineItem" rowKey="#{lineItem.lineItemId}"
resizableColumns="false" editable="#{view.editable}" editMode="cell"
editingRow="#{view.editable}" id="requestLineItemsTable">
<p:ajax event="cellEdit" listener="#{view.cellEdited}" immediate="true" update="#this" />
<p:column styleClass="centerColumnData" headerText="Item Name" style="width: 140px;">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{lineItem.title}"/>
</f:facet>
<f:facet name="input">
<h:inputText value="#{lineItem.title}"/>
</f:facet>
</p:cellEditor>
</p:column> ...
and this is the back end (not doing anything with this yet)
public void cellEdited(CellEditEvent event)
{
Object oldValue = event.getOldValue();
}
and here is the save and edit buttons on the same .xhtml page as datatable
<p:commandLink process="#this"
action="#{view.changeModeToEdit}"
update="#form"
rendered="#{!view.editMode">
<h:graphicImage library="images" name="edit20.png" title="#{__Common.edit}"
style="height: 15px; width: 15px;"/>
</p:commandLink>
<components:linkWithSpinner linkStyle="margin-right: 20px;" loadingImageStyle="margin-right: 20px;"
linkStyleClass="activeButton saveButtonRequestDetails" loadingImageStyleClass="saveButtonRequestDetails"
linkText="#{__CommonButton.save}"
process="#form" update="#form"
actionMethod="#{view.updateRequest()}"/>
view.updateRequest() sets the editable to false. I am using Primefaces 4.0
So I figured out a way around these issues. I was focused on using the built in edit table , but you can just have a normal datatable and the columns can contain input text fields. Then you don't have to worry about most of the issues in my question above. If you need to switch between edit and non-edit view then I still don't know how to fully fix it except have two datatables in your file with render tags, but then you are duplicating the table one with input text fields and one with output text fields, and that is not the best way to do it.

Hiding JSF elements with Java

The java code returns a column from a SQL query and if the item isn't null, sets the title to "Available".
String sppAcronym = results.getString("ACRONYM");
if (sppAcronym != null) {
sp.setFireStudyTitle("Available");
}
The JSF code makes a button labeled "Available" for all of the non-null items.
<h:column headerClass="columnHeader" footerClass="columnFooter" itemValue="0">
<f:facet name="header">Link to FEIS Fire Studies</f:facet>
<h:commandButton id="btnSearch" value="#{SPP.fireStudyTitle}"
action="#{searchBean.doMagic(SPP.acronym)}"
immediate="true" onchange="submit();"
style="font-weight:bold; font-size:small;"
onclick="javascript:cursor_wait()" class="buttonsFEIS"/>  
</h:column>
My problem is that JSF makes small, empty commandButtons even for the null items.
How can I make it so I can hide those empty commandButtons and display only the non-null items?
Use rendered attribute of the <h:commandButton> to control if the component must display or not in the generated HTML:
<h:commandButton id="btnSearch" value="#{SPP.fireStudyTitle}"
action="#{searchBean.doMagic(SPP.acronym)}"
immediate="true" onchange="submit();"
style="font-weight:bold; font-size:small;"
onclick="javascript:cursor_wait()" class="buttonsFEIS"
rendered="#{not empty SPP.acronym}" />

Update component without specifying the absolute client id

The code fragment below represents an editor. In my application, a windows displays a group of editors in a tab panel, each tab containing a datatable with the editors as rows. When a node is selected, its text will be displayed in the organizationUnit input text. The editor shouldn't know about it's parents. Is it possible to update organizationUnit without using the absolute client id?
<p:tabView value="#{accountsBean.groups}" var="group">
<p:tab title="#{eval.getString(group.name)}">
<p:dataTable value="#{group.editors}"
var="editor">
<p:column>
<custom:include src="#{editor.component}">
<ui:param name="bean" value="#{editor.beanName}"/>
<ui:param name="mandatory" value="#{editor.mandatory}"/>
<ui:param name="name" value="#{editor.name}"/>
</custom:include>
</p:column>
</p:dataTable>
</p:tab>
</p:tabView>
<h:panelGrid id="containerEditor" columns="2">
<h:outputText value="#{name}: #{mandatory ? '*' : ''}" />
<p:tree value="#{bean.root}" var="node" selectionMode="single" selection="#
{selectedNode}">
<p:ajax event="select" listener="#{bean.onNodeSelect}"
update="update_organization_unit" immediate="true" />
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
</p:tree>
<h:outputText />
<p:inputText id="organizationUnit" value="#{bean.selectedItemPath}"
disabled="true" />
</h:panelGrid>
The tab panel is inside a form called form with prependId="false"
When you have components inside different NamingContainers, and those are not nested**, you must use absolute client id.
In your case, if you don't use the separator character at the begining, the findComponent algorithm would search up until it finds a NamingContainer: this would be your p:tree. Then it would try to find the component inside the p:tree, since it's not there, the exception you mentioned is thrown.
On the other hand, If you do use the separator character at the begining, you must use the absolute client id.
Short answers: No. Unless you change the way your components are organized, you can't update organizationUnit without using the absolute client id.
** If NamingContainers are nested, components inside the outter NamingContainer may update ones inside an inner NamingContainer by referencing their id before the id of the actual component they want to update, for example: update="innerContainer1Id:componentId", or even update="innerContainer1Id:innerContainer2:componentId".
Algorithm is explained in the JavaDoc.
A common 'trick' I use to avoid refering to ids is to use binding.
Example:
<h:form>
<p:button binding="#{button}" ...
</h:form>
....
<p:button update=":#{button.clientId}" ...
Note: This doesn't work for some tags like h:outputText that don't generate an id.

<h:selectOneMenu> in jsf does not display any value in google chrome

<h:selectOneMenu class="medium" id="state" value="#{locationDataBean.stateSelected}" required="true" requiredMessage="Select State">
<f:selectItem itemLabel="Select State" itemValue="-1"/>
<f:selectItems value="#{systemResultViewUtil.stateList}"/>
<a4j:ajax event="change" listener="#{locationServiceBean.retrieveStateDetails()}" render="district,taluka,centerNameList1,stateMsg"/>
</h:selectOneMenu>
<h:message for="state" style="color: red" id="stateMsg"/>
This is the JSF tag that i have been using and the value="#{locationDataBean.stateSelected}" already contains the vlaue from the back bean. but still i dont get a the value selected on the page in chrome. it shows a blank record on the page. the value is obtained on the page and even when i inspect the element it shows the following html script
<option value="55" selected="selected">466-Assam </option>
but then also the value is not shown on the page.
If the selectbox HTML looks right yet you cannot see it on the rendered page, maybe your CSS class medium is defined to hiding it? Try removing the class attribute and see if this has any effect.
Did you try any other browser ?
Try value change listener in h:selectOneMenu element itself like
<h:selectOneMenu class="medium" id="state" value="#{locationDataBean.stateSelected}" required="true" requiredMessage="Select State" valueChangeListener="#{locationServiceBean.retrieveStateDetails}">
<f:selectItem itemLabel="Select State" itemValue="-1"/>
<f:selectItems value="#{systemResultViewUtil.stateList}"/>

Categories