Hide all primefaces blockui elements - jsf

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();
}
}
}
});

Related

How do I pass objects from the request map into a method expression after rendering a component?

I'm writing a custom datatable component, and I'm trying to allow other developers to use the var of the current iteration to be passed to a method expression.
Here's an example:
<my:dataTable value="#{contactController.viewEntities}" var="contact">
<p:column headerText="Whatever">
<p:commandButton value="Edit"
ajax="false"
actionListener="#{contactController.setSelectedContact(contact)}"
action="contact"/>
</p:column>
</my:dataTable>
As you can see, I'm trying to pass the "contact" var into a setter method for later use. That var is stored in the request map during rendering, like so:
...
Map<String, Object> requestMap = context.getExternalContext()
.getRequestMap();
for (Object obj : collection) {
requestMap.put(table.getVar(), obj);
for (UIColumn column : columns) {
column.encodeAll(context);
}
requestMap.remove(table.getVar());
}
...
However, when I run the project, the only value passed to the controller is null.
The question becomes, how do I make that object available for each row to use in expression language? I've looked at PrimeFaces'/ICEFaces' datatables, but I don't see how they differ from mine
Thanks in advance!
So, I finally solved this issue! When extending UIData, the method setRowIndex(index) becomes available. By setting this value, the clientId of each row's component will be prepended with the index number, thus making them unique per row. The trick was to set this value while iterating over the underlying collection. Expression language can now evaluate the var parameters.
int index = 0;
Map<String, Object> requestMap = context.getExternalContext()
.getRequestMap();
for (Object obj : collection) {
requestMap.put(table.getVar(), obj);
table.setRowIndex(index);
for (UIColumn column : columns) {
column.encodeAll(context);
}
requestMap.remove(table.getVar());
index ++;
}

Update Primefaces selectOneMenu from JavaScript

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.

Adding style to specific p:row

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).

JSF multiple groups of selectOneRadio on a page: how to recover the values?

I have a jsf page with multiple radiobutton groups (dynamically generated) on it. I need to retrieve the values from it in a backing bean, but fails to do so.
The business: a user wants to subscribe to a course that consists of multiple groups of coursedays. The user can choose the coursedays. So if a course consists of for example 4 coursedays, organised in 3 different groups, the user can choose from 12 coursedays, in blocks of 3.
The relevant part of the xhtml-page:
<c:forEach var="cd1" items="#{coursedayBean.getCoursedays(groupBean.getFirstGroup}">
<h:selectOneRadio value="#{subscriptionBean.selectedCoursedays[cd1.sequenceNr]}" >
<f:selectItems value="#{coursedayBean.getCoursedaysSelectItems}"/>
</h:selectOneRadio>
</c:forEach>
This results in a n*m matrix of radiobuttons where I want to retrieve n values.
The selectItems are of type <Long, String>.
In my backing bean, I declared the following:
public List<String> getSelectedCoursedays() {
return selectedCoursedays;
}
public void setSelectedCoursedays(List<String> selectedCoursedays) {
this.selectedCoursedays = selectedCoursedays;
}
I tried with a Map, List, but none of them worked. The setSelectedCoursedays is never called.
How do I declare the array/list/map to get the values in my backing bean?
#{subscriptionBean.selectedCoursedays[cd1.sequenceNr]}
doesn't do the trick.
This construct should work just fine. The setter will indeed never be called. JSF/EL just calls the setter on ArrayList itself by the add(index, object) method. I.e. it does basically:
subscriptionBean.getSelectedCoursedays().add(cd1.sequenceNr, selectedItem);
I'm not sure how you observed the concrete problem of "it doesn't work". Perhaps you were firing an ajax request and putting a breakpoint on the setter method and didn't read the server logs. There are two possible cases where this construct will fail.
If you don't prepare the selectedCoursedays with new ArrayList(), then you will get PropertyNotFoundException: Target Unreachable, 'selectedCoursedays' returned null.
If you don't fill the selectedCoursedays with the same amount of null items as the course days, then you will get an ArrayIndexOutOfBoundsException
So, you should prepare the selectedCoursedays as follows:
#PostConstruct
public void init() {
selectedCoursedays = new ArrayList<String>();
for (int i = 0; i < coursedays.size(); i++) {
selectedCoursedays.add(null);
}
}
Easier alternative is to make it a String[].
private String[] selectedCoursedays;
#PostConstruct
public void init() {
selectedCoursedays = new String[coursedays.size()];
}
It is miss understanding between c:forEach and ui:repeat. c:forEach will not build UI component tree nodes. Firstly, you have to reference difference between them here.

JSF 2.0 + Primefaces: Find all child components of a certain type

I have several different primefaces dialogs and I've implemented a close listener which receives a org.primefaces.event.CloseEvent. Inside of this close event I can access the UI component which generated the close event, org.primefaces.component.dialog.Dialog.
The problem I have is that I need to access all of the input fields which are on the dialog. These input fields may be buried inside other components on the dialog. Does anyone know of an easy way (one method call) to retrieve all of the child components which are input fields recursively?
Here is the solution I was able to come up with on my own:
private void doStuffToInputFields(UIComponent component) {
if (component instanceof UIInput) {
UIInput source = (UIInput) component;
//Add your custom logic here to do stuff with your input fields
return;
}
Iterator<UIComponent> children = component.getFacetsAndChildren();
if (children != null) {
UIComponent child = null;
while (children.hasNext()) {
child = (UIComponent) children.next();
resetInputFields(child);
}
}
}

Resources