A component for dynamic multiple group entries - jsf

I have come across a situation where in a form a customer needs to enter address. A customer can have more than one address and further the address field contains more than one text fields,combo boxes etc. A customer can dynamically add more address and remove any address entry. Eg: there is one add button on form, which when clicked will display all address fields as a group. if the user wants to add more address then he/she can again click the add button, so that a new entry for the address fields will be displayed. Also each corresponding new entry will have a delete button so that if the user wants to delete the entry then he/she can. Finally all the address entries should get mapped to a backing bean.
eg: in backing bean one has " private List address" and Address class further has street,pincode,state,city etc.
Is there any jsf ui component that can help out in the above scenario. In short, a user can enter more than one address dynamically and then a list of address gets mapped to the corresponding entry in backing bean..
Please guys, contribute for this, i am sure that this kind of component will make development way simpler.
The component should have the facility of describing our own sub group items. here in the above case it was address, but in different cases one might require it to be something else like mobile number, websites,email address etc. The component should be fully customizable ie. from group entries to mapping it.
Please developers, develop this kind of component and tell me from where and how can i start to be a part of it. If we all come together we can develop this wonderful component which will make development lot easier.

Ok, here's a a few ideas for you based on your narrative:
Make a form of <h:inputText> components bound to properties (Strings?) on your Backing Bean.
Make up a Class which describes a User's Address - UserAddress()?
Create a <h:commandButton> whose actionListener calls a method on the same backing bean, which creates a UserAddress() object from the values of the Strings on the backing bean, and then add it to a List of type List<UserAddress> on your Backing Bean.
Most JSF components are geared up to accept Lists of objects, so you'll be in a good position to then use such a component to loop over your List<UserAddress> to put all the user addresses on the screen.
There are plenty of component libraries out there to choose from. One which immediately comes to mind from the currently popular PrimeFaces library is the editable DataTable.
Good luck.

Related

Xpages: Dynamic View Panel and DominoViewCustomizer bean

I have dynamic view panel and I am using a customizer bean to hide columns based on column names. However, I need to:
Know which view is loaded in the customizer bean
get document handle in the bean
add additional column in the bean
Why I need this: in my application I am dealing with document mappings. I want to create a column for mapped document details. as there can be different document types mapped, there can be multiple columns.
The work of seeing which view you're working with and generating the column defs (normally the same as the ones in the view, but you could add others) is done via the ViewFactory object that is returned by #getViewFactory in the customizer bean. You can see an example of overriding the method and returning a customized factory here. You can also find the source of the default one in the ExtLib here for another example. The job of the ViewFactory is to emit a ViewDef containing a series of ColumnDefs - basically, an abstract representation of the view design. That will cover 1 and 3.
Getting a handle on the document in question for number 2 is a bit more indirect. Since the customizer bean executes only during the initialization of the view, it has no direct hook to the process of rendering each row (which is where you can get the document). You can, however, set properties or content to method/value bindings that, themselves, access the document, so that they're executed per row. I do this in order to get color columns working: I create an SSJS binding for the style property that can then see the viewEntry object. If you modify that code, you could write some SSJS like #{javascript:var doc = viewEntry.getDocument(); ...other stuff here...}. If you do that, you should make sure to either always use "viewEntry" as the var name in the view or use panel.getVar() to find the variable name dynamically.

Set current displayed tab programmatically in p:wizard

Is it possible to set current displayed tab programmatically in <p:wizard>?
For example, I want that for two different request to the same page which contains a wizard, to have a different tab selected.
What I am currently trying to do, is to have a wizard with many tabs, in the second tab I have a redirection to another page, so when I come back I want to come to the last step which caused the redirection.
Can you please help me ? Thank you a lot !
According to primefaces documentation there's a step attribute for p:wizard tag, which specifies the step of the wizard you're currently in.
attribute: step
default value: 0
type: String
description: Id of the current step in flow
You must bind this attribute to a value of your backing bean and maintain it during redirection and coming back. If your wizard's bean is #ViewScoped you'll loose that info during redirection step, so you have to pass it using a view param or flash scope.
My answer would most probably not meet your complete requirements, but, nonetheless, it may point you towards solution to your problem.
As far as I know, the PrimeFaces Wizard UIComponent is designed for a workflow of one page. That effectively means that inputs will be handled by a backing beans that is in a view scope.
This way, making a redirection on a certain step will clear all data inputs, because your view changes and the old one is destroyed.
Anyway, a means of setting a current tab for display is step attribute of Wizard component. So,
<p:wizard step="#{wizardBean.currentStep}" >...</p:wizard>
will force the wizard to show you step which you specified in your bean. You may be able to get it by using, for example, a view parameter, like in
<f:viewParam name="step" value="#{wizardBean.currentStep}" />
But it will make sense if lifetime of your bean is more that for a view, for example, the bean could be put in session scope.
That said, maybe it is a better idea to do login beforehand. Or, if it is absolutely necessary to do it in step 2 of your wizard, provide for a built-in login functionality in a page itself, or in a popular window?
Also, programmatically the setting you speak of can be achieved via a binding of component to your backing bean and setting the step value in the backing bean, for example, in a preRenderView event.

Audit trail for JSF application - Global valueChangeListener possible?

I am trying to implement an audit trail functionality for my web application that records:
lastModified (timestamp)
modifiedBy (user information)
userComment (reason for value change)
for each of my input fields (input fields are spread over several forms with different backing beans and different valueHolder classes).
The first two (lastModified and modifiedBy) are easily done with the help of an JPA AuditListener and #PrePersit and #PreUpdate methods.
The third one is a bit tricky since it requires user interaction. Best would be a dialog that asks for the user comment.
So there are (at least) two open issues: Can I establish a "global" valueChangeListener for all input fields in my application? Is this possible without attaching <f:valueChangeListener> to each single input component? Second: How can I grab the user comment. My idea is to put a p:dialog in my web page template but this dialog needs to know from which input component it is called.
Can I establish a "global" valueChangeListener for all input fields in my application? Is this possible without attaching to each single input component?
Yes, with a SystemEventListener which get executed during PreRenderViewEvent. You need to walk through the component tree as obtained by FacesContext#getViewRoot() to find all components which are an instanceofEditableValueHolder (or something more finer-grained) and then add the new YourValueChangeListener() by the addValueChangeListener() method. See also this answer how to register the system event listener: How to apply a JSF2 phaselistener after viewroot gets built?
Second: How can I grab the user comment. My idea is to put a p:dialog in my web page template but this dialog needs to know from which input component it is called.
You could in YourValueChangeListener#processValueChange() set the component in question as a property of some request or view scoped which you grab by evaluateExpressionGet().
Recorder recorder = (Recorder) context.getApplication().evaluateExpressionGet(context, "#{recorder}", Recorder.class);
recorder.setComponent(event.getComponent());
// ...
It will execute the EL and auto-create the bean in its scope if necessary. The bean in turn should also hold the property representing the user comment. Finally, you can use it in your <p:dialog>.
<p>You have edited #{recorder.component.label}, please mention the reason:</p>
...
<h:inputText value="#{recorder.comment}" />

JSF How to dynamic add new row to datatable

I am currently doing an online test system, I want allow admin to create a test and add in few question. I was thinking using datatable add in coloumn with textarea? how can i add new row? or is there any other suggestion to implement add new more questions.
Since you mentioned "admin", I think you probably mean you want to allow only users with certain rights to be able to add new question.
There are indeed more than one way to do it. It really depends on your requirements.
One example is you can add a [New Question...] h:commandButton in your page for users to navigate to another page for data entry. You may want to check whether the current user has the rights to navigate to the data entry page in the backing bean.
Then in the data entry page you have all your h:inputText, h:inputTextArea etc for users to enter their data/question. In this data entry page you can use a [Save] h:commandButton to submit the entered values, and then insert the submitted data in your backing bean.
If you preferred to use the add new row to datatable approach, BalusC has a very good write up in his blogspot http://balusc.blogspot.com/2006/06/using-datatables.html

Richfaces repeating elements

I'm trying to work on a user interface for adding "events". These events have either 0 or many contacts.
Ideally I would like to have an interface that when entering a new event, has a section for contacts, with a little form to enter one contact (name, phone, etc). On the bottom of that mini-form I would like to have a link or button saying "Add another" that would dynamically load another another mini contact form.
Is this possible with rishfaces/jsf?
Yes, it's doable. Adding another contact have to send ajax event to rerender contact list (addContact method need to result null to remain on the same page). After entering event data and selecting contact list the form will be submitted with event data.
The key elements are:
<a4j:commandButton value="Add contact" reRender="contactList" action="#{yourBean.addContact}" >
contact list may be created as <rich:orderingList id="contactList" ...> - see demo
If you want that panel with contact form initialy should be hidden you can use rendered property or use any collapsible component like <rich:simpleTogglePanel> or use <rich:modalPanel>
I thing it may help. Take a look of richfaces demo how to use a4j tags.
I believe it is as you would expect. Check out the following link, except replace the words ui:repeat with a4j:repeat
https://rogerkeays.com/jsf-c-foreach-vs-ui-repeat

Resources