I use JSF with Primefaces 3.5. I use the p:panelGrid without the columns attribute, instead I explicitly create rows and columns with p:row and p:column, as demonstrated in the showcase (http://www.primefaces.org/showcase/ui/panelGrid.jsf).
Now I need to style one row differently with the help of some CSS class. But either I am missing it or there is just no way to add a class to a p:row?! I can even set the attribute styleClass, but it is ignored in the rendered output ...
Is there a way to somehow distinguish a row within a panelGrid by its class?
Try using a wild card on the css (to math all td that ends with your id)
Like this (select all td that its id ends with myRowId)
tr[id*='myRowId'] {
color:red
}
Here a jsfiddle
Previous answer...
Since you can't use styleClass on p:row you can try the following
Assign that p:row an id, like this : <p:row id="myRowId "
And apply the style in the following way (in your css file)
#myFormId\3A SomeNamingContainer\3A myRowId {
background-color: red;
}
Do view source of your page in order to replace the myFormId and SomeNamingContainer with your real ids...
Also read this : How to use JSF generated HTML element ID in CSS selectors?
I don't know why the styleClass attribute is ignored by default (at least until PrimeFaces version 6.2), but you can create a custom renderer that appends its value to the HTML output. A simple drop in replacement for the default PrimeFaces renderer looks like this:
public class PanelGridBodyRowRenderer extends CoreRenderer implements HelperRowRenderer {
#Override
public void encode(FacesContext context, Row row) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String rowStyleClass = PanelGrid.TABLE_ROW_CLASS;
String userRowStyleClass = row.getStyleClass();
if (userRowStyleClass != null) {
rowStyleClass = rowStyleClass + " " + userRowStyleClass;
}
writer.startElement("tr", row);
writer.writeAttribute("class", rowStyleClass, null);
writer.writeAttribute("role", "row", null);
renderChildren(context, row);
writer.endElement("tr");
}
}
For PrimeFaces version 6.2 you can simply create this renderer class within the package org.primefaces.component.row.renderer in your WAR. The classloader will then load your renderer instead of the identical renderer class within the PrimFaces JAR.
For more information on custom components and renderers see this answer.
If you need the same style in others rows, maybe you can work with the column style from p:column (according with your response to Daniel). Something like this:
.stylePerColumn {
background-color: #F22626;
color: black;
border-style: none !important;
}
and int the xhtml file <p:column styleClass="stylePerColumn ">...</p:column> (to each column needed).
Related
I need to create a custom component that either extend or include a Primefaces SelectOneMenu. This is done so that I can deliver the select items based on the field (for now, they are hardcoded in the example below and the tag is properly registered).
The component is rendered and the select items are also displayed fine. However, when I save, the record's field is not updated with the selected item's value. Is there some primeface method I should override to actually set the value?
Are there any tutorials on how to extend primeface (or atleast jsf) components? I could hardly find any. Thank you in advance
#FacesComponent(value = ComponentRegistry.INPUT_SELECTDROPDOWN_COMPONENT_TYPE)
public class InputSelectDropdown extends SelectOneMenu {
#Override
public void encodeBegin(FacesContext context) throws IOException {
this.setValueExpression("value", this.getValueExpression("value"));
UISelectItem select1 = new UISelectItem();
select1.setItemLabel("item 1");
select1.setItemValue("item1");
select1.encodeAll(context);
this.getChildren().add(select1);
UISelectItem select2 = new UISelectItem();
select2.setItemLabel("item 2");
select2.setItemValue("item2");
select2.encodeAll(context);
this.getChildren().add(select2);
super.encodeBegin(context);
}
}
I am using a PrimeFaces' pickList with a custom converter.
JSF:
<p:pickList converter="costsConverter" value="#{offerController.costsAsDualListModel}" var="cost" itemLabel="#{cost}" itemValue="#{cost}" />
offerController.costsAsDualListModel looks like this:
public DualListModel<Cost> getCostsAsDualListModel() {
DualListModel<Cost> costsDualList;
List<Cost> costsSource = new ArrayList<Cost>();
List<Cost> costsTarget = new ArrayList<Cost>();
for (Cost c : costs) {
costsSource.add(c);
}
costsDualList = new DualListModel<Cost>(costsSource, costsTarget);
return costsDualList;
}
And my custom converter looks like this:
public String getAsString(FacesContext context, UIComponent component, Object object) {
if (object == null) {
return "";
}
Integer no = ((Cost) object).getNo();
String valueOf = String.valueOf(no);
return valueOf;
}
getAsString() is called and valueOf is correct but inside my picklist I still see the objects and not the return value fo getAsString().
I tried to use <f:converter converterId="costsConverter"/> within the picklist element. Same issue. Also I registered the converter in faces-config.xml:
<converter>
<converter-id>costsConverter</converter-id>
<converter-class>com.my.converter.CostsConverter</converter-class>
</converter>
What could be the problem?
You have a wrong understanding of values in components like picklists, selectonemenus, etc. These values are never displayed there but the labels are. And since converters are for values, not labels, you'll never see the converted value but the labels and everything behaves as it should. Just use itemLabel="#{cost.no}" and everything should be fine (display wise).
See e.g. how it is used in these two Q/A that also use a converter
How to write a custom converter for <p:pickList>
Primefaces Picklist Converter
Silly question, but that's my situation. I am having editable PrimeFaces selectOneMenu where inputField has following restriction:
lower and upper limit of number typed in
predefined text allowed
when decimal number is being typed allow only 2 decimal numbers
All is good except the last one with decimal number restriction. What it means is that I can't type there 1.111 but only 1.11. Change event keyUp for selectOneMenu is sadly added to the tag select but not to input.
Any ideas how to solve?
This calls for a custom validator. Create one which checks for the predefined values, if no match is found, check the number format. Basic example:
#FacesValidator("myValidator")
public class MyValidator implements Validator
{
private List<String> predefinedValues = Arrays.asList("my", "list");
#Override
public void validate(FacesContext context, UIComponent component, Object value)
throws ValidatorException
{
String valueStr = (String) value;
// Check if value is predefined
if (predefinedValues.contains(valueStr)) {
return;
}
// If not predefined, check number format
if (! valueStr.matches("^\\d+(\\.\\d\\d?)?$")) {
throw new ValidatorException(new FacesMessage("Value is invalid!"));
}
// Check number limits...
}
}
The validator can be used in your XHTML as:
<p:selectOneMenu editable="true" ...>
...
<f:validator validatorId="myValidator" />
</p:selectOneMenu>
As an alternative you could use jQuery to find the input field and bind a keypress listener to it. See for example: Jquery: filter input on keypress. However, I would keep the validator in place. Users could paste text for example.
See also:
How to perform validation in JSF, how to create a custom validator in JSF
Regular expression for floating point numbers
I have a lot of .xhtml views. Many of them have blockui elements, for example:
<p:blockUI block="tab" widgetVar="subscriberSelectBlocker">
</p:blockUI>
Sometimes there are more then 1 of them per view.
To hide the blockUI above I have a method in the according bean SubscriberFilterBean.java:
public void hideSubscriberSelectBlockUi() {
RequestContext.getCurrentInstance().execute("subscriberSelectBlocker.hide()");
}
Now the problem is that I need to hide all existing blockuis at once.
I could hide them individually like above, but that would mean that I would basically have the same code repeated over 15 times and the method to execute all these methods would be huge.
Is there a way to hide all elements of tag?
Something like
public void hideSubscriberSelectBlockUi() {
RequestContext.getCurrentInstance().execute("p:blockui.hide()");
}
When you are specifying widgetVar in a PrimeFaces element, JavaScript widget object is instantiated and assigned to a global variable with the specified name in the window scope. This means that this objects could be found and manipulated.
I suggest finding them by blockui ids. Widget object contains it's id, so after obtaining all the global objects and all the blockui ids from page, we can determine which of the global objects are blockui widgets. Blockui ids from page could be obtained using jQuery class selector, as they all have common css style: .ui-blockui.
Here is JavaScript example code that shows all blockui components on the page:
var keys = Object.getOwnPropertyNames( window );
var blocks = $('.ui-blockui');
var blockIds = [];
blocks.each (function (index,value) {
blockIds[index] = value.id;
});
$.each(keys, function (index, value) {
var obj = window[ value ];
if (obj != null) {
gObj = window[ value ];
if(gObj.blocker != undefined) {
if ($.inArray(gObj.blocker.attr('id'), blockIds) != -1) {
gObj.show();
}
}
}
});
I have a JSF form, that contains some JavaScript. When a specific input changes to a value >= 10 a selectOneMenu needs to dynamically change its option (which is yes or no).
My jQuery:
if ($("input[id*='inputBox']").val() >= 10) {
$("select[id*='selectOneMenu']").val("No");
} else {
$("select[id*='selectOneMenu']").val("Yes");
}
When I debug, the value in the selectOneMenu is changed correctly, but the UI component doesn't change its option. How do I tell the selectOneMenu to update its rendered value?
PrimeFaces SelectOneMenu is not a trivial select tag, it is a collection of divs put together to make it look like a select tag, use widgetVar.selectValue(val);
select tag is hidden inside the visible UI parts so that's why it is not working for you.
Your best bet will be to call a p:remoteCommand once the value should toggle. You will need to have the remoteCommand update your selectOneMenu ID (or IDs).
<p:remoteCommand name="setNo" actionListener="#{myBean.setNo}"
update="selectOneMenu" />
<p:remoteCommand name="setYes" actionListener="#{myBean.setYes}"
update="selectOneMenu" />
<SCRIPT>
var val="No"; //I'm assuming your initial value is "No"
if ($("input[id*='inputBox']").val() >= 10) {
if (val==="Yes") {
setNo();
val="No";
}
} else {
if (val==="No") {
setYes();
val="Yes";
}
}
</SCRIPT>
Then in your backing bean:
Map<String, String> selectBoxValues = ...
public void setNo() {
selectBoxValues.put("No", index);
}
[ditto for yes]
Of course, I've made up a bunch of variable names; you will have to change the text to suit your real variables.