Save all rows in an h:dataTable - jsf

I have a Facelets page with a h:dataTable. In each row of the h:dataTable, i am displaying some enabled and disabled services of a user.Here is the model object
public class ServiceList {
private long userId;
private long serviceGroupId;
private String serviceGroupName;
private long serviceId;
private String serviceName;
private String serviceUrl;
private String serviceState;
public UserServiceList() {
}
//getters and setters....
}
These are the details i am displaying in a single row of a dataTable.
serviceState in the above model object is either 'Y' or 'N'.
my problem is the application user should be able to update the servicestate of all rows of a dataTable at once and update them in the backend database.
1)what additional JSF component do i need to use inside dataTable to achive this? I am thinking of adding one more column with h:selectOneradio
2)How do i get which rows are selected and what status they have set?
I am kind of newbee to JSF.Please help.
Update:At present what i am having is two buttons namely 'Disable Service' and 'Enable Service' in the footer section of the table.
Onclick of Disable Service i am navigating to another page where i show the application user the list of enabled services to disable
And vice-versa for Enabled service button click.

So, let's say you in your Managed Bean you have a list of services you would like the user to edit:
List<Service> serviceList;
You take this List to be displayed in the data table.
<h:dataTable value="#{yourManagedBean.serviceList}" ... >
Then you can implement a commandButton that has either an action or an actionListener which points to a certain method of your managed bean, like this:
<h:commandButton action="#{yourManagedBean.saveAllAction}" ... >
And the corresponding method to save 'em all is quite straight-forward. You iterate over the managed bean field serviceList and persist every single entry (however you persist them, like calling the EntityManager when using Hibernate or any DAO class in between, you name it.)
Concerning the service status: I'd preferably use a selectBooleanCheckbox for toggling the status, since it's probably a boolean value.
Edit after comment 1:
You have the serviceStatus in your Service class. Currently it's a string, but I suppose it should be boolean to toggle active/inactive. If this property is displayed by the selectBooleanCheckbox it is automatically changed in your corresponding Java class. So calling getServiceStatus() returns true or false, depending on what is selected in the frontend. If you persist the whole Service object then, you don't have to do anything because any modifications made in the frontend HTML elements are automatically projected to the Java object behind it.

Related

Problem with Primefaces Autocomplete Component

I have a local Web Application developed with JDK 8, JSF 2.2 (implementation provided by JBoss), Spring 4.2 and Primefaces 6.2
In the application, I have one XHTML page for edit some fields of an object that is instance of a class named SiepRoEncabezado. One of those fields is an instance of SiepRpaPescador.
Until yesterday, I had one <p:selectOneMenu> contained in a form that is contained in a modal dialog in order to select one SiepRpaPescador object. The modal itself has 2 submit <p:commandButton> (one for save the changes and one for clean the form) and some aditional input fields.
The modal is developed in such manner that it closes automatiquely when the data is successfully edited after I push the save button.
The modal with the <p:selectOneMenu> worked fine, but due to the fact that there are too many select items to be handled in terms of memory usage, I was forced to replace the <p:selectOneMenu> by the following component:
<p:autoComplete dropdown="true"
id="rpaAutoComplete"
value="#{correccionROBean.tmpPescador}"
var="itemRpa"
itemLabel="#{itemRpa.nmPescador.concat(' ').concat(itemRpa.nmPaterno).concat(' ').concat(itemRpa.nmMaterno)}"
itemValue="#{itemRpa}"
completeMethod="#{correccionROBean.filtrarRpa}"
minQueryLength="4"
maxResults="10"
forceSelection="true" />
There, tmpPescador is a bean in the Managed Bean CorreccionROBean.
The complete method there works fine and the selection items are displayed as desired.
However, after I select one item in the <p:autoComplete> component and push the button to save the changes, it does nothing at all. Also, it does not display an error message and it does not throw any exception. What is worst, if I try to debug the action listener method in the button to save changes, it does nothing, it's like the action listener method is not called at all.
I put an <p:ajax> tag hoping to solve the problem with no avail:
<p:autoComplete dropdown="true"
id="rpaAutoComplete"
value="#{correccionROBean.tmpPescador}"
var="itemRpa"
itemLabel="#{itemRpa.nmPescador.concat(' ').concat(itemRpa.nmPaterno).concat(' ').concat(itemRpa.nmMaterno)}"
itemValue="#{itemRpa}"
completeMethod="#{correccionROBean.filtrarRpa}"
minQueryLength="4"
maxResults="10"
forceSelection="true">
<p:ajax event="itemSelect" listener="#{correccionROBean.onRpaSelect}" update="rpaAutoComplete"/>
</p:autoComplete>
Here, when I select one item, the listener method is not triggered. When I try to debug the method, it's like the method is not called at all.
Finally, when I push the save button without selecting an item in the <p:autoComplete>, then and only then, the action listener method in the save <p:commandButton> is triggered.
What may cause this behaviour?
Thanks in advance.
EDIT
I added the field immediate="true" to the autocomplete component and that triggered the ajax submit method, but still cannot execute the save button action listener method
SOLVED.
Refeer to Melloware's answer and my reply to that answer for more details.
For those that are unfamiliar with Converters:
The interface Converter, defined in JSF's API, allows to convert the data inputted and outputted to a Auto Complete component (and some other JSF UI components as well and their sub-classes). This interface has two methods:
public Object getAsObject(FacesContext context, UIComponent component, String value): This method must return an Object that is instance of the same class as the value defined in the value field of the Auto Complete component (in my case, it returns a SiepRpaPescador object). You must handle exceptions in this method as it is called automatiquely in two situations:
When you input characters in the Auto Complete text field and the number of inputted characters are equal or greater than the value defined in the minQueryLength field of the Auto Complete component or it's default value if not specified (in my case, when I input 4 characters or more). In this case, the value parameter in this method will be the String you inputted. Notice that if you enabled dropdown (dropdown="true")as in my case and you push the dropdown button, this method is NOT called.
When you submit the form. In this case, the value will be the value of the labelValue field in the Auto Complete component (in my case, #{itemRpa.nrFolio}) converted to String using the toString method defined in the class that value is instance of (#{itemRpa.nrFolio} is an Integer, so the value will be converted using the Integer class' own implementation of toString()) or in the Object class if no implementation of toString() is defined.
public String getAsString(FacesContext context, UIComponent component, Object value): This method must return a String representation of the label value of each item to be displayed in the Auto Complete component. The parameter value is an instance of the same class as the value defined in the labelValue field of the Auto Complete component. This method is called automatiquely when the items are displayed (it doesn't matter if you inputted characters in the Auto Complete's text field or pressed the dropdown button if present) and it's called as many times as defined in the field maxResults (in my case, 10) in the Auto Complete, using the objects obtained from the returned list of the completeMethod (in my case, from each object in the list obtained from #{correccionROBean.filtrarRpa}, this method obtains it's nrFolio, as I stablished in the labelValue field of the AutoComplete).
I hope this helps to you all

SelectOneMenu does not display list items

EDIT
Here is a generic example that I recreated
I am using JSF2.3 and primefaces 6.2.2
I have 3 SelectOneMenu Components (Country, State, City) that I am trying to populate from a MySql database. The problem is that when I persist for example, country (USA) and in the same session, when I try to add a state, the selectOneMenu list (Country list) does not show the just persisted country value in the drop down list.
The backing bean is #ViewScoped which I think is the issue. But, I feel that this is the right scope. I also noticed that the #PostConstruct init() method is not called just before the dialog is displayed which is the right behavior for a bean with #ViewScoped. It gets called at the beginning of the session.
Not sure if there is an event that I need to look at. Thanks for your help!

Access a component of a custom control

I have a custom Control which I'll call ccViewTemplate with this code in it:
<xp:repeat id="repeatData" rows="30"
value="#{viewEntry}" var="veData"
first="#{javascript:return (sessionScope.ssFirst != null)?sessionScope.ssFirst:0;}">
<xp:panel id="panelSelect">
<xp:callback facetName="viewBodyFacet" id="callback1"></xp:callback>
</xp:panel><!-- panelSelect -->
</xp:repeat>
the database view (viewEntry) is also defined in ccViewTemplate and defined based on several custom properties. ccViewTemplate is then added to another custom Control called ccFinalView. Where the custom properties are entered, and the content of the display is entered into viewBodyFacet. I have access to veData and a everything works great to this point. In the viewBodyFacet I have a link that does a redirect to open the document which also works fine. However, in the link I want to get the repeatData Property First and store it so that it returns to the correct page of the repeat. I use this code:
sessionScope.put('ssFirst',getComponent("repeatData").first);
However, the code can not find the getComponent("repeatData") because it is inside ccViewTemplate and not accessible. Is there a way to get the component repeatData from the ccViewTemplate while in ccFinalView which contains ccViewTemplate.
I have done getComponent("ccViewTemplate") and I have the handle to the custom Control, but
getComponent("ccViewTemplate").getComponent("RepeatData").first fails. So is there a way to pull a value from a component 'inside' a custom control from 'outside' the custome control?
looked a little further and found this:
var rtn = getComponent("ccViewTemplate").getPropertyMap().getProperty("repeatData");
It does not generate an error but returns nothing, if I add
var rtn = getComponent("ccViewTemplate").getPropertyMap().getProperty("repeatData").first;
I get an error getComponent() is null
Hope this makes sense.
From what I understand, this is a perfect job for a java bean. The bean can even keep a default value.
public class Controller{
public String value;
public Controller(){
value = "default_value";
}
public String getValue(){return value;}
public void setValue(String value){this.value=value}
}
In this fashion, the value will be available as soon as the object is created. pressing the button then sets the value with javascript,
ControllerBean.setValue("thisValue");
and you can read the value
ControllerBean.getValue();
This question shows how to configure the bean: How to set up a managed bean to work with Notes document
By setting this to, say the viewScope, you can then access the value anywhere you need regardless of whether or not it is in a custom control or main page. I highly recommend this approach. It just means possibly rethinking your custom control structure.
EDIT
Extra ideas include having an enum that maintains the views,
public enum Views{
VIEW_1("viewAlias", "urlParam")
private String vwAlias;
private String urlParam;
private Views(String alias, String param){
vwAlias = alias;
urlParam = param;
}
// public getters
}
And then in your controller you can get the view string:
1. By seeing if a view param is included in the URL
2. If a cookie value is set
3. Take the hard coded default
Clicking the change view action then sets the cookie value and changes the view parameter and redirects.
This is all extra ideas, but it is how I build my view controllers. I will be doing a tutorial on that soon.

adf managed bean retrieving a value from input text

I'm trying to retrieve a value from an input text in my jsf page, but when I change its value it doesn't change in the managed bean.
here's the input text:
<af:inputText label="Código:" id="codigo" value="#{tipoBaixaBean.codigo}"/>
and my managed bean is annotated like this:
#ManagedBean
#RequestScoped
public class TipoBaixaBean {
private long codigo;
I have the getters and setters, but the value of the property "codigo" never changes,
What would be the problem??
Thank you
Change your Bean scope to 'pageFlowScope' or 'viewScope' in adfc-config.xml . That should do.
You don't say when you are trying to get the value...on page submit or when you tab out of the field. If you want the value when you tab out (lose focus) then set the autoSubmit property on the input text field to true.
I would also suggest using a print statement in set method to make sure it's being called. The scope issue only arises if you are trying to retain the value between page requests.
Not sure how can you bind an inputText to a long object in backing bean.
Ideally it should be something like
private RichInputText codigo;
you can get the value of codigo using the getter.
getCodigo.inputValue();
I don't think scope will cause any problem. It works for the least life scope i.e. backing bean scope.
It really depends on the exact moment in which you are getting/setting the value, but if you need to do it automatically every time a change occurs, then you'll need to implement the Value Change Listener. Check this out: Value Change Listener example

Commandlink action and #viewscoped weird behaviour

I have some code generated by netbeans wizard 'JSF pages from entity classes'.
For those who don't use netbeans I will briefly describe what the wizard does.
It creates a JSF page List.xhtml which contains a datatable with a fixed size of ten rows and two commandlinks for scrolling its content (prev 10 and next 10).
The JSF page uses a managedbean with session scope and the above mentioned commandlinks return the String 'List'.
If I change the managed bean scope to #viewscoped it is re-created every time I push a commandlink. According to me it is a weird behavior because the view actually doesn't change (it always List.xhtml ) and I would have expected a smarted view scope mechanism.
I then changed the action associated to the commandlinks with a new one which does the same things but returns void. Now the #viewscope mechanism works well but I'm not sure it is correct to use an action method with a signature like this
public void doSomething()
// instead of
public String doSomething()
My concern is that a different JSF implementation can act in an impredictable way with that kind of actions.
Thanks
Filippo
What do you return in public String doSomething()?
If you return null (or an empty String) it should not re-create the view.
If you return a navigation case then the view is re-created, regardless whether it is the same that you are currently in.

Resources