<h:selectOneMenu> doesn't save on the bean the value selected - jsf-2

I have problems with SelectOneMenu. I write this:
<h:selectOneMenu id="listaEstados"
styleClass="comboboxStyle"
value="#{detalleSistemaBean.sistema.indEstado}"
immediate="true">
<f:selectItems value="#{detalleSistemaBean.indEstados}" />
</h:selectOneMenu>
<h:commandButton id ="SubmitModificar"
value="Modificar"
styleClass="botonPeque"
action="#{detalleSistemaBean.modificaSistema}">
</h:commandButton>
But when I choose one value from the list "indEstados" and I submit the form, the bean "sistema.indEstado" doesn't change. I have seen that the bean property changes just before the method modificaSistema, but inside this method (where I have a database connection and a sql sentence), "sistema.indEstado" returns to its original value. Why this happens? I have tried to save the value using valueChangeListener, and that works, but I guess that is not a neat solution.

That can happen when you're doing data loading inside the getter method instead of inside the (post)constructor of the bean class.
Fix your managed bean code to not do anything else inside getter methods than just returning the property.
I.e. do not do
public Sistema getSistema() {
return sistemaService.find(someSistemaId);
}
but rather do
private Sistema sistema;
#PostConstruct
public void init() {
sistema = sistemaService.find(someSistemaId);
}
public Sistema getSistema() {
return sistema;
}

Can you try without setting
immediate="true"
JSF commandButton with immediate="true"

Related

Dialog close instanciate Bean ViewScoped

I have a form where I have a button, when I click on that button, a Dialog opens to select a value and then my dialog close.
But, doing this my Bean (#ViewScoped) is called again (re-instantiated) and I lose my information that I previous entered on page.
I searched and I found a similar behaviour (http://forum.primefaces.org/viewtopic.php?f=3&t=38235) but no answer.
I initialize my bean with constructor but I don't know if this is the problem.
#ManagedBean(name="exameBean")
#ViewScoped
public class ExameBean implements Serializable {
public ExameBean(){
exame = new Exame();
exames = new ArrayList<Exame>();
}
public void selecionaPaciente() {
RequestContext.getCurrentInstance().openDialog("/pages/SelecionaPaciente");
}
public void retornaPaciente(Paciente paciente) {
RequestContext.getCurrentInstance().closeDialog(paciente);
}
public void pacienteSelecionado(SelectEvent event) {
exame.setPaciente((Paciente) event.getObject());
}
}
SelecionaPaciente.xhtml
<p:column headerText="Selecionar">
<p:commandButton icon="ui-icon-search" actionListener="#{exameBean.retornaPaciente(lista)}" />
</p:column>
May you need to use #SessionScoped, when you use #ViewScoped and show a dialog, you lose the actual instance of you MB. I had the same problem today and i solved using a init method annoted with #PostConstruct (To Load all my data ) and annotate with #SessionScoped to use and manage my data loaded from init().

Making valueChangeListener on h:inputHidden fire a ManagedBean method

My JavaScript:
function setJson(value) {
document.getElementById("json").value = value;
}
My XHTML:
<h:inputHidden id="json" value="#{indexManaged.json}" valueChangeListener="#{indexManaged.goTo('datatable')}" />
My ManagedBean:
#ManagedBean
#ViewScoped
public class IndexManaged implements Serializable {
private String json;
public String getJson() { return json; }
public void setJson(String json) { this.json = json; }
public String goTo(String page) {
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
flash.put("json", json);
return page + "?faces-redirect=true";
}
}
The scenario:
I have a Java Applet that fires the function setJson(value). But when the applet sets a new value to my inputHidden, isn't the valueChangeListener suposed to fire my ManagedBean method? What am I doing wrong?
The valueChangeListener isn't a client side listener. It's a server side listener which runs when the form is submitted. So, you need to submit the form as well.
Wrap it in a form
<h:form id="form">
and submit it as follows
document.getElementById("form").submit();
Don't forget to fix the client ID of the hidden input accordingly:
document.getElementById("form:json").value = value;
See also:
When to use valueChangeListener or f:ajax listener?
Unrelated to the concrete problem, there are cleaner ways to achieve this. Have a look at PrimeFaces <p:remoteCommand> and OmniFaces <o:commandScript>.
Not sure about the <h:inputHidden
But you can use the following thing:
<h:inputText id="json" value="#{indexManaged.json}" style="display:none">
<f:ajax listener="#{myBean.myListener}"/>
</h:inputText>
and trigger it with jquery like this:
$("#json").change();// instead of `json` you might be needed to provide
//full id like this, $("#myform\\:json").change()

JSF2.0 backing bean setter not invoked when using dataTable

I have a screen in which am using
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:body>
<h:form>
<f:event listener="#{pageload.getPageLoad}" type="preRenderView" />
<h:dataTable value="#{pageload.fieldConfig}" var="field"
columnClasses="lblFirstCol,lblSecondCol,lblThirdCol,lblFourthCol" id="table1" styleClass="tblSecond" >
<h:column >
<h:outputText value="#{field.label_name}" />
</h:column>
<h:column>
<h:inputText value="#{searchdevice.device.terminal_name}" />
</h:column>
</h:dataTable>
<h:commandButton value="Submit" action="#{searchdevice.searchButtonAction}"/>
</h:form>
</h:body>
And my backing bean
#ManagedBean(name="pageload")
#RequestScoped
public class PageLoadBean {
private List<FieldConfigVO> fieldconfig;
//getters and setters
// method to populate the ArrayList
public void getPageLoad(){
//getting populated from Database
fieldconfig = common.getFieldConfig("001");
}
}
The other input bean
#ManagedBean(name="searchdevice")
#RequestScoped
public class SearchDeviceBean {
private DeviceVO device;
public SearchDeviceBean() {
device = new DeviceVO();
}
public DeviceVO getDevice() {
return device;
}
public void setDevice(DeviceVO device) {
this.device = device;
}
public String searchButtonAction(){
System.out.println(device.getTerminal_name()+"****TERMINAL NAME******");
FacesContext context = FacesContext.getCurrentInstance();
if (context.getMessageList().size() > 0) {
return(null);
}else {
return("success");
}
}
}
My Device Object has the terminal_name property.I have a command button which invokes method in SearchDeviceBean and on submitting the form whatever value I enter doesn't get populated
Any help appreciated
You're performing data initialization logic in preRenderView event. This is the wrong place for code which needs to prepare the model for the postback. When JSF needs to update the model values during form submit, it is encountering a completely empty fieldConfig and therefore JSF can't set the submitted/converted/validated values in there. The fieldConfig is in your case only prepared during a later phase, the render response phase, which is thus too late.
You need to initialize it in #PostConstruct instead. It's invoked immediately after bean's construction and dependency in jection. Get rid of the whole <f:event> altogether and put a #PostConstruct annotation on the getPageLoad() method. I'd by the way also rename that method to init() or loadFieldConfig() as it isn't a getter method at all and therefore a very confusing name to other people reading/maintaining your code.
See also:
When to use f:viewAction / preRenderView versus PostConstruct?

how to initialize jsf 2.0 textfield on runtime?

I would like to initialize my textfield at runtime. For example, I have primefaces inputtext like this:
<p:inputText value="#{myBean.value}" id="inputText" />
And a bean class:
#PostConstruct
public void onPageLoad() {
....
....
inputText.setMaxlength(15);
inputText.setStyle(".....");
}
Is it possible to do this with jsf 2.0?
You could do so by binding the component to the bean:
<p:inputText binding="#{bean.input}" ... />
with
private InputText input; // +getter+setter
#PostConstruct
public void init() {
input = new InputText();
input.setMaxlength(15);
input.setStyle("background: pink;");
}
// ...
This is however not the recommended approach. You should rather bind the individual attributes to a bean property instead.
<p:inputText ... maxlength="#{bean.maxlength}" style="#{bean.style}" />
with
private Integer maxlength;
private String style;
#PostConstruct
public void init() {
maxlength = 15;
style = "background: pink;";
}
// ...
Even more, if your app is well designed, then you should already have such a bean object for this (why/how else would you like to be able to specify it during runtime?). Make it a property of the managed bean instead so that you can do something like:
<p:inputText ... maxlength="#{bean.attributes.maxlength}" style="#{bean.attributes.style}" />
For this you can fetch component object from jsf framework using below code
UIComponent componentObj = FacesContext.getCurrentInstance().getViewRoot().findComponent(id)
then you can type cast component object in your tag component type like if you are using inputText
HtmlInputText inputTextObj = (HtmlInputText) componentObj;
and HtmlInputText class have all the getter setter for all available attribute in tag
so you can set values like
inputTextObj.setMaxlength(15);
inputTextObj.setStyle(....);
inputTextObj.setDisabled();
inputTextObj.setReadonly();

View scoped managed bean with setPropertyActionListener

I cant seem to get the view scoped managed bean to work with setPropertyActionListener:
<h:commandButton value="Edit" action="edit-company.xhtml">
<f:setPropertyActionListener target="#{companyHolder.item}" value="#{company}"/>
</h:commandButton>
This works fine if companyHolder is session or request scoped but doesnt work if its view scoped. Is this normal?
A brand new view scoped bean is been created when a new view is created. The target view holds a different instance of the view scoped bean than where the property is been set by the action method on the initial view with the form.
This is at first sight indeed unintuitive, but that's how the view scope works. A view scoped bean lives as long as the view lives. It makes sense after all.
Your best bet is using <f:param> instead of <f:setPropertyActionListener> and let the target view set it by <f:viewParam>.
E.g.
<h:commandButton value="Edit" action="edit-company.xhtml">
<f:param name="companyId" value="#{company.id}"/>
</h:commandButton>
with
<f:metadata>
<f:viewParam name="companyId" value="#{bean.company}" required="true" />
</f:metadata>
and
#ManagedBean
#ViewScoped
public class Bean {
private Company company;
// ...
}
and
#FacesConverter(forClass=Company.class)
public class CompanyConverter implements Converter {
#Override
public void getAsObject(FacesContext context, UIComponent component, Object value) throws ConverterException {
try {
return companyService.find(Long.valueOf(value));
} catch (Exception e) {
throw new ConverterException(new FacesMessage(
String.format("Cannot convert %s to Company", value)), e);
}
}
// ...
}
As a completely different alternative, you can also just navigate back to the same view by returning void or null and render the include conditionally.
<ui:include src="#{bean.editmode ? 'edit' : 'view'}.xhtml" />
This however doesn't work if you require to support GET instead of POST (for which you would need to replace <h:commandButton> by <h:button> by the way).

Resources