Is it possible to use OmniFaces <o:validateAllOrNone> (which is pretty cool ;)) within an <ui:repeat> or <h:dataTable>?
I need a table with each row having an input field column. You could either fill in none of these values or all of them.
If I put the <o:validateAllOrNone> within the <ui:repeat> or <h:dataTable> and use the id of the input field in components attribute, then the validator also gets triggered, if all fields are empty.
No, that's not possible. The components attribute must refer physically multiple components, not a single component which is rendered multiple times. It can however be used on physically multiple components which are rendered during same iteration round. The <o:validateXxx> multi field validator is not designed to reference a single component which is rendered multiple times. The only OmniFaces validator which does that is <o:validateUniqueColumn>.
If you want to use the <o:validateXxx> multi field validator on dynamic inputs based on a collection, then your best bet is to use JSTL <c:forEach>. It will build physically multiple components.
E.g.
<c:forEach items="#{bean.items}" var="item" varStatus="loop">
<h:inputText id="input_#{loop.index}" value="#{item.value}" />
</c:forEach>
Assuming that there are 3 items, this will dynamically create JSF components with IDs of input_0, input_1 and input_2. Then you can just use <o:validateXxx> as follows (put it outside the loop!)
<o:validateAllOrNone components="input_0 input_1 input_2" />
You can replace the hardcoded string in the above example by an EL expression which returns the desired space separated string of component IDs from a backing bean.
<o:validateAllOrNone components="#{bean.inputIds}" />
An alternative would be to create a <x:validateAllOrNoneColumn> yourself or to post an enhancement request at OmniFaces issue tracker. It would be not exactly trivial to alter the existing <o:validateAllOrNone> that a completely separate component is desired.
Related
There are lot of materials out there differentiating value attribute and binding attribute in JSF.
I'm interested in how both approaches differ from each other. Given:
public class User {
private String name;
private UICommand link;
// Getters and setters omitted.
}
<h:form>
<h:commandLink binding="#{user.link}" value="#{user.name}" />
</h:form>
It is pretty straight forward what happens when a value attribute is specified. The getter runs to return the name property value of the User bean. The value is printed to HTML output.
But I couldn't understand how binding works. How does the generated HTML maintain a binding with the link property of the User bean?
Below is the relevant part of the generated output after manual beautification and commenting (note that the id j_id_jsp_1847466274_1 was auto-generated and that there are two hidden input widgets).
I'm using Sun's JSF RI, version 1.2.
<form action="/TestJSF/main.jsf" enctype="application/x-www-form-urlencoded"
id="j_id_jsp_1847466274_1" method="post" name="j_id_jsp_1847466274_1">
<input name="j_id_jsp_1847466274_1" type="hidden" value="j_id_jsp_1847466274_1">
Name
<input autocomplete="off" id="javax.faces.ViewState" name="javax.faces.ViewState"
type="hidden" value="-908991273579182886:-7278326187282654551">
</form>
Where is the binding stored here?
How does it work?
When a JSF view (Facelets/JSP file) get built/restored, a JSF component tree will be produced. At that moment, the view build time, all binding attributes are evaluated (along with id attribtues and taghandlers like JSTL). When the JSF component needs to be created before being added to the component tree, JSF will check if the binding attribute returns a precreated component (i.e. non-null) and if so, then use it. If it's not precreated, then JSF will autocreate the component "the usual way" and invoke the setter behind binding attribute with the autocreated component instance as argument.
In effects, it binds a reference of the component instance in the component tree to a scoped variable. This information is in no way visible in the generated HTML representation of the component itself. This information is in no means relevant to the generated HTML output anyway. When the form is submitted and the view is restored, the JSF component tree is just rebuilt from scratch and all binding attributes will just be re-evaluated like described in above paragraph. After the component tree is recreated, JSF will restore the JSF view state into the component tree.
Component instances are request scoped!
Important to know and understand is that the concrete component instances are effectively request scoped. They're newly created on every request and their properties are filled with values from JSF view state during restore view phase. So, if you bind the component to a property of a backing bean, then the backing bean should absolutely not be in a broader scope than the request scope. See also JSF 2.0 specitication chapter 3.1.5:
3.1.5 Component Bindings
...
Component bindings are often used in conjunction with JavaBeans that are dynamically instantiated via the Managed
Bean Creation facility (see Section 5.8.1 “VariableResolver and the Default VariableResolver”). It is strongly
recommend that application developers place managed beans that are pointed at by component binding expressions in
“request” scope. This is because placing it in session or application scope would require thread-safety, since
UIComponent instances depends on running inside of a single thread. There are also potentially negative impacts on
memory management when placing a component binding in “session” scope.
Otherwise, component instances are shared among multiple requests, possibly resulting in "duplicate component ID" errors and "weird" behaviors because validators, converters and listeners declared in the view are re-attached to the existing component instance from previous request(s). The symptoms are clear: they are executed multiple times, one time more with each request within the same scope as the component is been bound to.
And, under heavy load (i.e. when multiple different HTTP requests (threads) access and manipulate the very same component instance at the same time), you may face sooner or later an application crash with e.g. Stuck thread at UIComponent.popComponentFromEL, or Threads stuck at 100% CPU utilization in HashMap during JSF saveState(), or even some "strange" IndexOutOfBoundsException or ConcurrentModificationException coming straight from JSF implementation source code while JSF is busy saving or restoring the view state (i.e. the stack trace indicates saveState() or restoreState() methods and like).
Also, as a single component basically references the rest of the entire component tree via getParent() and getChildren(), when binding a single component to a view or session scoped bean, you're essentially saving the entire JSF component tree in the HTTP session for nothing. This will get really costly in terms of available server memory when you have relatively a lot of components in the view.
Using binding on a bean property is bad practice
Regardless, using binding this way, binding a whole component instance to a bean property, even on a request scoped bean, is in JSF 2.x a rather rare use case and generally not the best practice. It indicates a design smell. You normally declare components in the view side and bind their runtime attributes like value, and perhaps others like styleClass, disabled, rendered, etc, to normal bean properties. Then, you just manipulate exactly that bean property you want instead of grabbing the whole component and calling the setter method associated with the attribute.
In cases when a component needs to be "dynamically built" based on a static model, better is to use view build time tags like JSTL, if necessary in a tag file, instead of createComponent(), new SomeComponent(), getChildren().add() and what not. See also How to refactor snippet of old JSP to some JSF equivalent?
Or, if a component needs to be "dynamically rendered" based on a dynamic model, then just use an iterator component (<ui:repeat>, <h:dataTable>, etc). See also How to dynamically add JSF components.
Composite components is a completely different story. It's completely legit to bind components inside a <cc:implementation> to the backing component (i.e. the component identified by <cc:interface componentType>. See also a.o. Split java.util.Date over two h:inputText fields representing hour and minute with f:convertDateTime and How to implement a dynamic list with a JSF 2.0 Composite Component?
Only use binding in local scope
However, sometimes you'd like to know about the state of a different component from inside a particular component, more than often in use cases related to action/value dependent validation. For that, the binding attribute can be used, but not in combination with a bean property. You can just specify an in the local EL scope unique variable name in the binding attribute like so binding="#{foo}" and the component is during render response elsewhere in the same view directly as UIComponent reference available by #{foo}. Here are several related questions where such a solution is been used in the answer:
Validate input as required only if certain command button is pressed
How to render a component only if another component is not rendered?
JSF 2 dataTable row index without dataModel
Primefaces dependent selectOneMenu and required="true"
Validate a group of fields as required when at least one of them is filled
How to change css class for the inputfield and label when validation fails?
Getting JSF-defined component with Javascript
Use an EL expression to pass a component ID to a composite component in JSF
(and that's only from the last month...)
See also:
How to use component binding in JSF right ? (request-scoped component in session scoped bean)
View scope: java.io.NotSerializableException: javax.faces.component.html.HtmlInputText
Binding attribute causes duplicate component ID found in the view
each JSF component renders itself out to HTML and has complete control over what HTML it produces. There are many tricks that can be used by JSF, and exactly which of those tricks will be used depends on the JSF implementation you are using.
Ensure that every from input has a totaly unique name, so that when the form gets submitted back to to component tree that rendered it, it is easy to tell where each component can read its value form.
The JSF component can generate javascript that submitts back to the serer, the generated javascript knows where each component is bound too, because it was generated by the component.
For things like hlink you can include binding information in the url as query params or as part of the url itself or as matrx parameters. for examples.
http:..../somelink?componentId=123 would allow jsf to look in the component tree to see that link 123 was clicked. or it could e htp:..../jsf;LinkId=123
The easiest way to answer this question is to create a JSF page with only one link, then examine the html output it produces. That way you will know exactly how this happens using the version of JSF that you are using.
I'm creating an inline text editor. I've written the code to edit one single h:ouputText field (h:inputHidden). Works. Thus, I thought I create a composite (widget), that I can call for every field I want to update. Of course, those fields refer to a managed bean in my case, that is the PubController MB.
<composite:interface name="inlineEditor">
<composite:attribute name="attrOfMb" required="true"
type="java.lang.String" />
<composite:attribute name="pubController" required="true" type="com.playground.webapp.controller.PubController"/>
</composite:interface>
Now, I have the following tasks to accomplish:
pass the MB to the composite (done).
in the composite, create the div and the hidden input field with id of the MB attribute.
Challenge where I struggle:
How do I "bind" an attribute of the passed PubController to the hidden input field? #{cc.attrs.pubController.title}? Well, it should not always be the same attribute. The attribute should be chosen by what has been passed in the interface attribute attrOfMb.
In other cases, its not necessariley PubController. Might be another MB. My initial thought was to define the interface type to javax.faces.bean.ManagedBean. On the other hand, how could you then "bind" the passed MB to the input hidden field (respectively vice-versa).
Is there a JSF-Pattern on how you accomplish these things?
You're going in the wrong path as to designing the composite. You should bind a bean property, not a whole bean.
I.e. you should not have
<my:composite bean="#{bean}" />
but you should have
<my:composite value="#{bean.value}" title="#{bean.title}" />
Once you fix that problem, then you can easily reuse it on any backing bean. Please note that this is also the way how standard JSF <h:xxx> components work. If you worry about about "too many" attributes for some unclear reason, then just create a reusable model class which in turn can be a property of the backing bean.
<my:composite data="#{bean.data}" />
This way you can use it further in the composite as #{cc.attrs.data.value}, #{cc.attrs.data.title}, etc.
If you really, really need to bind a whole bean, then I'd question if a tag file or maybe an include file isn't a better solution for whatever functional requirement you've had in mind. A composite component should really represent a component with a single responsibility and a single point of model value binding.
See also:
When to use <ui:include>, tag files, composite components and/or custom components?
Using expression language, how can I access a component that is bound and repeated in a datatable?
<h:dataTable value="#{bean.items}" var="item" id="table">
<h:column>
<h:inputText value="#{item.name}" id="name" binding="#{mybinding}"/>
</h:column>
</h:dataTable>
Should I give each binding a generated name with a concatenation of a literal and the row index, for instance ('mybinding_1', 'mybinding_2', and so forth), and if so, how?
Or instead is there a way to get a particuliar element with #{mybinding} plus some kind of brace notation ([])?
There's a misconception going here. There are definitely not physically multiple <h:inputText> components in the component tree. There's only one component whose HTML representation is generated multiple times depending on the current state of the parent table component. You can confirm this by walking through the component tree starting at FacesContext#getViewRoot(), you'll ultimately find only one <h:inputText> component.
So, binding="#{mybinding}" is perfectly fine.
If you're having problems with it, it's caused elsewhere and needs to be solved differently. Only and only if you're using a view build time tag to generate physically multiple components in a loop, such as JSTL <c:forEach>, then there would indeed be physically multiple <h:inputText> components in the component tree and you'd need to bind them to an array or map. But this is currently clearly not the case.
I'm developing a data-centric Web Application using JSF 2.1 and PrimeFaces 3.4.
As a result of a specific query, I must display the results in a bi-dimensional data table with some dynamic columns (imagine a sort of Pivot-table).
Currently I use a PrimeFaces <p:dataTable> with some standard <p:column> tags and a <p:columns> for the dynamically-created columns. The table is backed by a #ViewScoped Managed Bean.
It works fine, but:
Just like a pivot-table, I need to display multiple headers too, in
order to group some fields together. Unfortunately, <p:columns> is
not compatible with <p:columnGroup> (nor with many other features
like resizing etc.)
I need to display some custom sub-total rows (is there a way to
do this?)
I was thinking about populating the entire <p:dataTable> programmatically, but I can't use binding="#{...}" with a #ViewScoped bean due to JSF issue 1492.
I am trying to bind a label 2 (or more!) fields in a dataset in Silverlight 4. I get a localized string out of a resource file and do a String.Format on it like so:
<TextBlock Name="lblTotals" Text="{Binding TotalItems, StringFormat='You need \{0\} items and \{1\} products.'}" />
This works fine with 1 item but there's no way of doing multiple binds in SL4 it seems.
I found some blog posts on how to bind a single element to multiple fields but it does not seem to support the String.Format part which is critical.
The last caveat is that it is bound to an ObservableCollection, so when these fields change in the data the UI must update too.
Any suggestions? Thanks!
I found a solution here using a converter and binding to the whole object and passing in the string as a converter param.
Then the totals did not update when the grid values updated (despite being linked to OnPropertyChanged) - this was the solution hack here.