Reputation: 435
I am trying to display all available FontAwesome icons in a p:selectOneMenu
component.
The renderer is supposed to render the icon first, then display the icon's name. A similar example can be found here but is implemented especially for BootStrap: https://mjolnic.com/fontawesome-iconpicker/
---------------------------------- |- ICON - | Icon name | ----------------------------------
Unfortunately, the custom columns just do not get rendered. The p:selectOneMenu
appears but is rendered as by default.
My picker xhtml page looks as follows:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html 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">
<h:head></h:head>
<body>
<p:panel>
<h:form id="iconPicker">
<p:selectOneMenu id="iconSelectOneMenu"
value="#{iconController.availableIconStrings}">
<f:selectItem itemLabel="Choose icon"
noSelectionOption="true" />
<f:selectItems
value="#{categoryController.availableIconStrings}"
var="_icon" itemValue="#{_icon}"
itemLabel="#{_icon}" />
<p:column>
<p:button id="iconButton" icon="#{_icon}" />
</p:column>
<p:column>
<h:outputText value="#{_icon}" />
</p:column>
</p:selectOneMenu>
</h:form>
</p:panel>
</body>
</html>
The IconController
class:
public class IconController implements Serializable {
private List<String> availableIconStrings;
public IconController() { }
@PostConstruct
public void init() {
availableIconStrings = new ArrayList<>();
availableIconStrings.addAll(Arrays
.asList("fa-adjust,fa-adn,fa-align-center,fa-align-justify,fa-align-left,"
+ "fa-align-right,fa-ambulance,fa-anchor,fa-android,fa-angellist,"
+ "fa-angle-double-down,fa-angle-double-left,fa-angle-double-right,"
+ "fa-angle-double-up,fa-angle-down,fa-angle-left,fa-angle-right"
// Shortened list
.split(",")));
}
public List<String> getAvailableIconStrings() {
return availableIconStrings;
}
public void setAvailableIconStrings(List<String> availableIconStrings) {
this.availableIconStrings = availableIconStrings;
}
}
As you can see, I am trying to render the icon using a p:button
. Do I understand it correctly that I need a PrimeFaces component that is able to display icons (e.g. p:button
, p:commandButton
, p:commandLink
) to achieve my goal?
Any help is appreciated. Thanks a lot.
P.S.: Using PrimeFaces 5.3, JSF 2.2 and Mojarra on WildFly 9.0.2
Upvotes: 3
Views: 7585
Reputation: 20168
See https://www.primefaces.org/showcase/ui/input/oneMenu.xhtml for an example:
<p:outputLabel value="Icons" />
<h:panelGroup styleClass="ui-inputgroup">
<h:panelGroup id="icon" styleClass="ui-inputgroup-addon">
<i class="pi pi-#{selectOneMenuView.icon}"/>
</h:panelGroup>
<p:selectOneMenu value="#{selectOneMenuView.icon}" var="item">
<f:selectItems value="#{['flag','wallet','map','link']}" var="item" itemLabel="#{item}"
itemValue="#{item}" />
<p:column><i class="pi pi-#{item}" /> #{item} </p:column>
<p:ajax update="@parent:@parent:icon" />
</p:selectOneMenu>
</h:panelGroup>
It is a workaround, yes, but it's the best option currently.
See also:
Upvotes: 0
Reputation: 1116
Use inputGroup
<div class="ui-inputgroup">
<div class="ui-inputgroup-addon"><i class="pi pi-user"></i></div>
<p:inputText placeholder="Username"/>
</div>
https://www.primefaces.org/showcase/ui/input/inputGroup.xhtml
Upvotes: 0
Reputation: 435
For simplicity and re-usability, I decided to wrap the String
s in an Icon
class and not to follow implement a different Renderer
class as suggested by BalusC in the workaround (https://stackoverflow.com/a/32740430/2118909).
public class Icon {
private String fontIconName;
public Icon(String fontIconName) {
this.fontIconName = fontIconName;
}
public String getFontIconName() {
return fontIconName;
}
public void setFontIconName(String fontIconName) {
this.fontIconName = fontIconName;
}
}
The JSF page looks as follows:
<p:selectOneMenu id="iconSelectOneMenu"
value="#{iconController.selectedIcon}" var="_icon" converter="#{iconConverter}">
<f:selectItem itemLabel="Choose icon"
noSelectionOption="true" />
<f:selectItems
value="#{categoryController.availableIcons}" itemValue="#{_icon}"
itemLabel="#{_icon.fontIconName}" />
<p:column>
<i class="fa fa-fw #{_icon.fontIconName}"/>
</p:column>
<p:column>
<h:outputText value="#{_icon.fontIconName}" />
</p:column>
</p:selectOneMenu>
Please also note the following:
#{iconController.selectedIcon}
now refers to an instance of the Icon
class#{iconController.availableIcons}
now refers to a List<Icon>
instanceConverter
for the Icon
class. <i/>
element.Please also note the importance and role of the customContent
variable in the SelectOneMenuRenderer.encodePanel(...)
method which indicates that you need a var
value on the p:selectOneMenu
directly (not in the <f:selectItems/>
element!) or the renderer will not recognize that there is custom content as it does not evaluate the <f:selectItems/> var
attribute.
Upvotes: 2
Reputation: 6040
Two things:
In order to use p:column
in combination with p:selectOneMenu
you need to declare the var
attribute on the p:selectOneMenu
and reference it within your p:column
. An example can be found on the PrimeFaces showcase.
So your code should be:
<p:selectOneMenu id="iconSelectOneMenu"
value="#{iconController.availableIconStrings}" var="ic">
<f:selectItem itemLabel="Choose icon"
noSelectionOption="true" />
<f:selectItems
value="#{categoryController.availableIconStrings}"
var="_icon" itemValue="#{_icon}"
itemLabel="#{_icon}" />
<p:column>
<p:button id="iconButton" icon="#{ic}" />
</p:column>
<p:column>
<h:outputText value="#{ic}" />
</p:column>
</p:selectOneMenu>
Now, You are facing a bug because you are using a List<String>
as explained on this SO question:
So, if the item value is an instance of String, custom content via
p:column
is totally ignored.
You can find a workaround in the same post: https://stackoverflow.com/a/32740430/2118909
Upvotes: 1