<p:selectOneMenu> with bold labels for some items - jsf

I'm trying to have a Primefaces "SelectOneMenu" with items that can either have a "normal" label or a "bold" label. I tried 2 different variants, but both don't work as expected.
Variant 1:
<p:selectOneMenu id="menu" value="#{selected}">
<f:selectItems value="#{mySelectItems}"/>
</p:selectOneMenu>
public List<SelectItem> getMySelectItems() {
List<SelectItem> list = new ArrayList<SelectItem>();
for (...) {
SelectItem item = new SelectItem(value, label);
item.setEscape(false);
if (...)
item.setLabel("<b>" + item.getLabel() + "</b>");
list.add(item);
}
return list;
}
This way I can have some of the items in the menu with a bold label and some with a normal label. The problem: The field that is showing the current selection is displaying the text as "< b >...< /b >". The text doesn't seem to be escaped, but it seems that it just can't be displayed as bold, because it's inside an HTML label. I don't know how I could get rid of the "< b >" and "< /b >" in that label, though.
Variant 2:
<p:selectOneMenu id="menu" value="#{selected}" var="myClass">
<f:selectItems value="#{myClasses}"/>
<p:column>
<h:outputText value="#{myClass.name}" styleClass="bold"/>
</p:column>
</p:selectOneMenu>
public List<MyClass> getMyClasses() {
List<MyClass> list = new ArrayList<MyClass>();
...
return list;
}
With this variant I can also have bold labels for items (currently all of them) in the menu. The problem is: The text showing the current selection doesn't show "myClass.getName()", but instead "myClass.toString(). The labels in the menu are correct. Is there a way to fix this?
If I write...
<f:selectItems value="#{myClasses}" var="myVar" itemValue="#{myVar.value}" itemLabel="#{myVar.name}"/>
instead, then it doesn't display the items in the menu as bold anymore, but it's using getName() instead of toString() in the field of the current selection.
Does anyone know how to get my ideas to work the way I want them to work or maybe have a better idea on how to solve this?
Thanks in advance!

In Variant 2 you need to provide converter for MyClass by implementing javax.faces.convert.Converter. Converter needs only for selection (it generates string representation of the object (unique id of instance) and converts it back to object after processing). And for correct representation of selected value you need add this attributes to selectItems: <f:selectItems value="#{myClasses}" var="myVar" itemValue="#{myVar}" itemLabel="#{myVar.name}"/>.
<h:outputText styleClass="bold"... will effect only for list of selectItems. To change style of selected item you need to add styleClass to p:selectOneMenu. In your case:
<p:selectOneMenu id="menu" value="#{view.selection}" converter="#{view.myClassConverter}"
var="v" style="#{(view.selection.name eq 'bold-name') ? 'font-style: bold' : null}">
<f:selectItems value="#{view.myClasses}" var="mc"
itemLabel="#{mc.name}" itemValue="#{mc}"/>
<p:column>
<h:outputText value="#{v.name}" style="#{(v.name eq 'bold-name') ? 'font-style: bold' : null}"/>
</p:column>
<p:ajax event="change" update="menu" process="#this"/>
.

Related

Filter p:datatable by boolean column (checkbox)

I am trying to filter my primefaces datatable by a boolean column using a checkbox filter but unfortunately filtering in primefaces datatable seems it does not work with any type other than String, but there should be a workaround for this case.
datatable column
<p:column headerText="A_boolean_column" filterBy="#{myBean.myBoolean}" filterMatchMode="exact">
<f:facet name="filter">
<p:selectCheckboxMenu label="BooleanFilter" onchange="PF('mydatatable').filter()" styleClass="custom-filter">
<f:selectItems value="#{myBean.possibleAnswers}" />
<p:ajax update="#form" oncomplete="PF('mydatatable').filter();"/>
</p:selectCheckboxMenu>
</f:facet>
<h:outputText value="#{myBean.myBoolean}"/>
</p:column>
where possibleAnswers variable is a list that has been initialized on init method of myBean with true && false values
#PostConstruct
public void init(){
this.possibleAnswers= new ArrayList<>();
possibleAnswers.add(true);
possibleAnswers.add(false);
}
I have similar working examples in my datatable with text values and are working perfectly. Of course I could do a workaround to fix my issue by converting the values from boolean ( true / false) into String ("true" / "false") ( or even write a custom function to check for equality)but I don't really like this solution and I would prefer any other out of the box solution ( perhaps a different filterMatchMode ? ).
I am using primefaces 7.0
Normally an input component has a 'value' attribute that is bound to a field (getter/setter) in a backing bean. The type of this field can be used to automatically convert the technical string of the http request to the correct java type. For a datatable filter this cannot be automatically done since there is no value attribute. Giving all components knowledge about all possible containers they can be used in is bad design. So the only and corrrect solution is to use an explicit converter.
Have a Look at the Implementation of the Status-Column in the PrimeFaces datatable filter showcase, as far as I see it it is exactly what you need
for Reference:
<p:column filterBy="#{myBean.myBoolean}" filterMatchMode="in">
<f:facet name="filter">
<p:selectCheckboxMenu label="BooleanFilter"
onchange="PF('mydatatable').filter()" styleClass="custom-filter">
<f:converter converterId="javax.faces.Boolean" />
<f:selectItems value="#{myBean.possibleAnswers}" />
<p:ajax update="#form" oncomplete="PF('mydatatable').filter();"/>
</p:selectCheckboxMenu>
</f:facet>
</p:column>

How to create a textfield cell in primefaces datatable with action that do a computation

I'm currently working on a dynamic datatable. Let's say this table has 4 columns (name, x, y, z). x, y must be number text field and z is a label which shows the sum of x and y. When the values on either x or y is changed the value on z must be recomputed.
My problem right now is I'm not able to bind the text fields to the datatable entity, if I use the edit from primefaces, I need to add an edit event which I don't like. Also it display the cell initially as label, then need to click it to show the textfield.
Any suggestions? Thanks.
Here's my solution, instead of using primefaces datatable.edit feature. I just use a textfield in the cell and added a p:ajax that triggers a recompute method on change. Note the use of update parameter, we can directly reference a field on the row.
<h:form id="creditNoteLinesForm">
<p:dataTable id="resultsId_creditNoteLines" var="entity"
value="#{creditNoteBean.entity.creditNoteLines}">
<!-- // -->
<p:column
headerText="#{messages['creditNote.list.amountWithoutTax']}">
<p:inputText value="#{entity.amountWithoutTax}">
<p:ajax event="change"
listener="#{creditNoteBean.reCompute(entity)}"
update="amountWithTax"></p:ajax>
</p:inputText>
</p:column>
<p:column headerText="#{messages['creditNote.list.amountTax']}">
<p:inputText value="#{entity.taxAmount}">
<p:ajax event="change"
listener="#{creditNoteBean.reCompute(entity)}"
update="amountWithTax"></p:ajax>
</p:inputText>
</p:column>
<p:column
headerText="#{messages['creditNote.list.amountWithTax']}">
<h:outputText id="amountWithTax" value="#{entity.amountWithTax}" />
</p:column>
</p:dataTable>
</h:form>
sdfdsf
public void reCompute(CreditNoteLine line) {
line.computeWithTax();
}

h:selectOneMenu in p:dataTable doesn't submit its value

I have a question about selectOneMenu and settting the values. I have an Object SampleDesc that has and ID, Text, and a List<SampleDescValues>. For each datatable row the Text is the output label and the select one menu values are the List<SampleDescValues>.
XHTML:
<h:panelGroup id="tables">
<p:dataTable resizableColumns="true"
var="sampleDesc" id="SampleDescTable" rowIndexVar="rowIndex"
value="#{sampleBean.sampleDescList.list}"
rendered="#{sampleBean.sampleDescList.list.size() gt 0}">
<p:column>
<h:outputLabel value="#{sampleDesc.sampleDescText}"/>
</p:column>
<p:column>
<h:selectOneMenu required="#{sampleBean.sampleDescList.list.size() gt 0}" converter="#{sampleDescValueConverter}"
id="SampleDescValue" value="#{sampleBean.selectedSampleDescList.get(rowIndex)}">
<f:selectItem itemLabel="Select One" itemValue="#{null}"/>
<f:selectItems value="#{sampleDesc.sampleDescValues}" var="sdv"
itemLabel="#{sdv.sampleDescValuesText}" itemValue="#{sdv}" />
</h:selectOneMenu>
</p:column>
</p:dataTable>
</h:panelGroup>
I have the converter setup and it works because ive set it to a single SampleDescValue and it set the value.
The problem is when i try and populate the form with a Sample from the database it can only set one of the dropdowns when there could be an infinite number of selectonemenu's
I set the value selected to private List<SampleDescValue> selectedSampleDescList;
When i try and submit it does nothing, it works when the datatable is not rendered.
Your menu value is wrong:
<h:selectOneMenu value="#{sampleBean.selectedSampleDescList.get(rowIndex)}">
It's not possible to perform a set operation on this EL expression.
Use the brace notation instead:
<h:selectOneMenu value="#{sampleBean.selectedSampleDescList[rowIndex]}">
Note that this expects a non-null selectedSampleDescList. So make sure that you've already properly initialized it with a new ArrayList<>() beforehand. EL won't do that for you. It will only set the list items using List#add(index, object) method.
See also:
Our EL wiki page
Unrelated to the concrete problem, this expression
#{sampleBean.sampleDescList.list.size() gt 0}
can be simplified as follows
#{not empty sampleBean.sampleDescList.list}
And this is unnecessary in the required attribute of the <h:selectOneMenu> as it would always evaluate true at that point. Just use required="true" directly instead.

How to retrieve and show list of values in listbox and text corresponding to list item in textarea

I need to use a list box to show some values from database and do further processing when a single value from the list is selected.
At the PrimeFaces showcase site the example loads fixed (static) data into the listbox and there is one PrimeFaces command for each list item. How do I show items in a list box dynamically, when I may not know the number of items beforehand?
I also need to show some text corresponding to the item selected in list, in a textarea. Do I have to use an event listener for this purpose? I would like to leave the text area blank at the beginning. Only when a value is selected in the list box, then I want to use a bean to retrieve and store data using that textarea. Is this possible? How do I implement this?
How do I show items in a list box dynamically, when I may not know the number of items beforehand?
Use <f:selectItems> which you bind to a List<T> property. Basic example, assuming you're using EJB/JPA to interact with DB:
private Item selectedItem; // +getter+setter
private List<Item> availableItems; // +getter
#EJB
private ItemService service;
#PostConstruct
public void init() {
availableItems = service.list();
}
with
<p:selectOneListbox value="#{bean.selectedItem}" converter="itemConverter">
<f:selectItems value="#{bean.availableItems}" var="item"
itemValue="#{item}" itemLabel="#{item.someLabel}" />
</p:selectOneListbox>
The itemConverter should implement javax.faces.convert.Converter and convert from the Item object to its unique string representation (usually its DB identifier) in getAsString() and convert the other way round getAsObject().
I also need to show some text corresponding to the item selected in list, in a textarea. Do I have to use an event listener for this purpose?
Just put a <p:ajax> (the PrimeFaces equivalent of standard JSF <f:ajax>) in the listbox which updates the textarea. E.g.
<p:selectOneListbox value="#{bean.selectedItem}" converter="itemConverter">
<f:selectItems value="#{bean.availableItems}" var="item"
itemValue="#{item}" itemLabel="#{item.someLabel}" />
<p:ajax update="textarea" />
</p:selectOneListbox>
<p:inputTextarea id="textarea" value="#{bean.selectedItem.someText}" />
It'll be invoked when you select an item.
See also:
Our h:selectOneMenu wiki page - same applies to PrimeFaces p:selectOneListbox
Yes, for demonstration purposes most of the examples are loaded with static data. But if you look at the same example on PF showcase, the second listbox code is as follows:
<h:outputText value="Scrollbar: " />
<p:selectOneListbox id="scroll" value="#{autoCompleteBean.selectedPlayer1}"
converter="player" style="height:100px">
<f:selectItems value="#{autoCompleteBean.players}"
var="player" itemLabel="#{player.name}" itemValue="#{player}" />
</p:selectOneListbox>
and f:selectItems value attribute can point to a collection, an array, a map or a SelectItem instance. So coming to the above example players could be any list that is being populated using a database in the managed bean.
But if the instance is not a SelectItem, the labels are obtained by calling a toString on each object and finally the selected itemValue is set to the selectedPlayer1 attribute but you can also see that there is a converter in between so the incoming itemValue string is converted back to a player object and then set to selectedPlayer1.
And if you want to display the selected item in a text area, you can do something like this:
<h:outputText value="Scrollbar: " />
<p:selectOneListbox id="scroll" value="#{autoCompleteBean.selectedPlayer1}"
converter="player" style="height:100px">
<f:selectItems value="#{autoCompleteBean.players}"
var="player" itemLabel="#{player.name}" itemValue="#{player}" />
<p:ajax update="displayArea"/>
</p:selectOneListbox>
<p:inputTextarea id="displayArea" value="#{autoCompleteBean.selectedPlayer1}" />
Here the inputTextarea is updated using ajax with the value selected by the user.

How do I add a selected value to ice:selectOneMenu?

I'm facing a problem with the ice:selectOneMenu component in Icefaces..
In more details :
When I fill the SelecItems arrayList I set an empty selcetItem at the first index in the arrayList, like that : mainClassificationsSI.add(new SelectItem(""));, and in My page I have the following :
<ice:selectOneMenu partialSubmit="true" binding="#
{editOutgoingBean.mainClassificationSelect}" id="mBookClass" value="#
{editOutgoingBean.outgoing.main_Classification}" valueChangeListener="#
{editOutgoingBean.mainClassificationChanged}">
<f:selectItems value="#{editOutgoingBean.mainClassificationsSI}"/>
</ice:selectOneMenu>
First of all, I'm sure that the: editOutgoingBean.outgoing.main_Classification has value which is one of the values of selectItems in the SelectItems arrayList, but when the page is displayed, the Select tag select the empty value and it didn't select the value of the main_Classification I set before...
When I remove the first Empty SelectItem from the ArrayList, the Select tag will select the value that I set for main_Classification. Please help me find out what to do...
try this ,may help you.
<ice:selectOneMenu partialSubmit="true" binding="#
{editOutgoingBean.mainClassificationSelect}" id="mBookClass" value="#
{editOutgoingBean.outgoing.main_Classification}" valueChangeListener="#
{editOutgoingBean.mainClassificationChanged}">
<f:selectItem itemLabel="Select" itemValue="-1" />
<f:selectItems value="#{editOutgoingBean.mainClassificationsSI}"/>
</ice:selectOneMenu>`
and don't the black select item from the bean as you were doing

Resources