Action/ActionListener method checked even if rendered=false - jsf

I have a composite component representing a table, that depending on the editable attribute (which I have created) may or may not display links to edit a row.
The edit links are of type <h:commandLink> and have actionListeners pointing to a method in a backing bean. The backing bean for handling editing is provided as a <cc:attribute name="editBean"... /> like the attribute editable, when I want the table to be editable.
If I don't need the table to be editable I set the editable attribute to false and the links rendered attribute gets set to false as well.
My problem is that if I set editable to false and therefore don't set the attribute editBean either, I get errors pointing out that there is no method for handling editing (e.g. java.lang.String does not have the property xxxxx).
I had hoped that as the links are set to not be rendered at all, what has been specified in the action/actionListener would be ignored. To me it feels logical to first check the rendered attribute and then, if it's set to true, check the other attributes.
So, my questions are: why does it work like this and if there's an elegant way of handling this scenario?

Use JSTL <c:if> to conditionally build the component in JSF component tree instead of rendered attribute to conditionally render the HTML output (it's that you're using JSF 2.2, otherwise I'd have explicitly mentioned that this requires a minimum of Mojarra 2.1.18 to avoid broken view state).
<c:if test="#{cc.attrs.editable}">
<h:commandLink ... />
</c:if>

Related

When is the attribute's value of a Primefaces component updated?

I would like to understand when and how often an attribute's value is updated. I often see that component's attributes are updated even thought I didn't explicitly call an update on the component.
For example:
<p:panel id="panelA"
styleClass="#{controller.conditionA ? '.styleA' : 'styleB'}"
rendered="#{controller.conditionB() }">
</p:panel>
When the conditionB changes from true to false, the panels rendered attribute is updated as well without me calling an updated on the panel with panelA.
How are the both attributes styleClass and rendered evaluated and when?
Are all attributes, which have a non-static value, evaluated and updated periodically?
Instead of the panel, styleClass and rendered there could be other Primefaces components and attributes. I am interested in the general mechanism behind that.

rowkey attribute in primefaces is not rendered, without selection or selectionMode attribute

I want use the rowkey attribute within a datatable primefaces (for use it in javascript script),
but I've noticed that is necessary set at least the selectionMode or selection attribute,
otherwise the rowkeyattribute (data-rk) is not rendered.
It 's true, or am I wrong?
I did some tests and it seems to be so.
Below an example from the showcase:
(rowkey attribute seems to be always used in combination with the selectionMode or selection attribute)
http://www.primefaces.org/showcase/ui/data/datatable/selection.xhtml
I would need to take advantage of the rowkey attribute without using selectionMode or selection attribute;
you would know how to do?
Or, you know how to set a custom attribute for each row of datatable without using the component p:row;
The only thing that comes to mind is use the rowClass attribute to insert in, the value of a bean property,
as is the case here
http://www.primefaces.org/showcase/ui/data/datatable/rowColor.xhtml
But I wanted to associate the property of the bean to a specific attribute of row without creating a fake class CSS.
thanks in advance
I assume that you want to achieve the presence of 'data-rk' attribute on a <tr> without the rendering of the selection column.
I did some tests and if you put this styling on the then you will not have the selection column but still the 'data-k' attribute:
<p:column selectionMode="multiple" style="display: none;" />
You have to put this tag, but you do not need to place the selection attribute on the <p:dataTable>.
If this is what you are looking for, then this worked for me on Primefaces 6.0 and JSF 2.2

Missing parameter values in invoked method with composite components using ui:repeat

So after several days of debugging, we were eventually able to reproduce some strange interactions between composite components, ui:repeat, p:remoteCommand and partial state saving in JSF that we do not understand.
Scenario
A composite component iterates over a list of objects using ui:repeat. During each iteration, another composite component is included and arguments are passed.
<ui:composition (...)>
<ui:repeat var="myVar" value="#{cc.attrs.controller.someList}">
<namespace:myRemoteCommand someParam="SomeParam"/>
In the included composite component, there is an auto-run p:remoteCommand calling a method using parameters defined in the component's interface.
<ui:component (...)>
<p:remoteCommand actionListener="#{someBean.someMethod(cc.attrs.someParam)}"
autoRun="true"
async="true"
global="false">
However, when setting a breakpoint in someMethod(...), an empty string is passed. This only happens if partial state saving is set to false.
Solutions
We tried several solutions and the following ones appear to work (however we do not understand why and cannot foresee any further problems that could occur):
We can set partial state saving to true.
We can change the composite component pattern to ui:include.
We can remove one or both of the composite components and directly include the content instead.
Question
Why does JSF behave this way? What is this interaction between composite component, ui:repeat and argument passing that changes depending on whether we use ui:include / partial state saving or not?
We're using Primefaces 5.3, Glassfish 4.1, Mojarra 2.2.12, Java 8.
Your code is all fine. It's just that Mojarra's <ui:repeat> is broken. You're not the first one facing a state management related problem with <ui:repeat>.
Checkbox inside ui:repeat not refreshed by Ajax
Dynamically added input field in ui:repeat is not processed during form submit
Components are with the same id inside ui:repeat
<h:form> within <ui:repeat> not entirely working, only the last <h:form> is processed
Composite component with custom backing component breaks strangely when nested inside ui:repeat
ui:repeat in o:tree not working as expected
Root cause of your problem is that #{cc} is nowhere available at the moment the <ui:repeat> needs to visit the tree. Effectively, the <ui:repeat value> is null. A quick work around is to explicitly push the #{cc} in UIRepeat#visitTree() method. Given Mojarra 2.2.12, add below lines right before line 734 with pushComponentToEL(facesContext, null).
UIComponent compositeParent = getCompositeComponentParent(this);
if (compositeParent != null) {
compositeParent.pushComponentToEL(facesContext, null);
}
And add below lines right after line 767 with popComponentFromEL(facesContext).
if (compositeParent != null) {
compositeParent.popComponentFromEL(facesContext);
}
If you don't build Mojarra from source, copy the entire source code of UIRepeat into your project, maintaining its package structure and apply above changes on it. Classes in /WEB-INF/classes have higher classloading precedence than those in /WEB-INF/lib and server's /lib. I have at least created issue 4162 to address this.
An alternative is to replace Mojarra by MyFaces, or to replace the <ui:repeat> by an UIData based component which got state management right such as <h:dataTable> or <p:dataList>.
<p:dataList type="none" var="myVar" value="#{cc.attrs.controller.someList}">
<namespace:myRemoteCommand someParam="SomeParam" />
</p:dataList>
You might only want to apply some CSS to get rid of widget style (border and such), but that's trivial.
See also:
Should PARTIAL_STATE_SAVING be set to false?

JSF Required=Yes not working inside a datatable?

I searched everywhere but could not find a solution to this. I am trying to used
required=yes to validate whether a value is present or not. I am using it inside inputtext.
The problem is it does not work inside a datatable. If I put the text box outside the datatable it works. I am using JSF 1.7 so I don't have the validateRequired tag from JSF 2.0.
I even used a validator class but it is still not working. Does anyone know why does required=yes or validator='validationClass' inside a inputtext inside a datatable is not working.
I appreciate the help.
Thanks.
First of all, the proper attribute values of the required attribute are the boolean values true or false, not a string value of Yes. It's an attribute which accepts a boolean expression.
The following are proper usage examples:
<h:inputText required="true" />
<h:inputText required="#{bean.booleanValue}" />
<h:inputText required="#{bean.stringValue == 'Yes'}" />
As to the problem that it doesn't work inside a <h:dataTable>, that can happen when the datamodel is not been preserved properly (the datamodel is whatever the table retrieves in its value attribute). That can in turn happen when the managed bean is request scoped and doesn't prepare the datamodel during its (post)construction which causes that the datamodel is null or empty while JSF is about to gather, convert and validate the submitted values.
You need to ensure that the datamodel is exactly the same during the apply request values phase of the form submit request as it was during the render response phase of the initial request to display the form with the table. An easy quick test is to put the bean in the session scope. If that fixes the problem, then you definitely need to rewrite the datamodel preserving logic. You could also use Tomahawk's <t:saveState> or <t:dataTable preserveDataModel="true"> to store the datamodel in the view scope (like as JSF2's new view scope is doing).
Finally, JSF 1.7 doesn't exist. Perhaps you mean JSF 1.2?

rendered attribute on inputText

I have a search form tied to a backing bean that contains 4 input text fields. The design i am working from indicates that the user should be able to see the search results, but they should not be editable. i decided to use the rendered attribute to show the inputs if the managed bean is empty, and to show an output text tag if it's not:
<t:inputText styleClass="inputText" id="name" rendered="#{not searchCriteria.fieldsEntered}"
value="#{searchCriteria.name}" autocomplete="off"></t:inputText>
<h:outputText value="#{searchCriteria.name}" rendered="#{searchCriteria.fieldsEntered}"></h:outputText>
The display part works correctly, but I am noticing that only the first field is stored in the managed bean when more than 1 search field is entered.
I removed a rendered attribute from an inputText, and sure enough that's causing my problems. I can infer what's going on here, but I don't understand why.
I believe in this situation I will just remove the outputText tags and change rendered to disabled. I am just curious why my initial plan is incorrect.
The rendered="false" will cause the input element not being rendered and thus its value will not be submitted to the server side. If you're using a request scoped bean, the initial value will not be set. You'd like to either put the bean in session scope or to add a h:inputHidden along the h:outputText which transfers the value to the subsequent request.
Since you're already using Tomahawk's t:inputText I'd suggest to rather use its displayValueOnly attribute instead of the rendered attribute and a complementary h:outputText.
In a nut:
<t:inputText displayValueOnly="#{searchCriteria.fieldsEntered}" ... />

Resources