ValueChangeListener not being invoked upon submit - jsf

My valuechangelistener method is not being called as I expected. I have a h:selectOneRadio component (below) and I'm expecting the valueChangeListener to be called when I click the add button, but only the add method is getting invoked, the setSelectedItem method is completely ignored. What am I missing? Note the javascript dataTableSelectOneRadio is executing fine.
Here is the .xhtml
h:panelGrid
Select Client to Associate with Appointment
<h:dataTable id="addClient" styleClass="dataTable"
value="#{AddEntryMB.clientValues}" var="c" binding="#{AddEntryMB.dataTable}" >
<h:column>
<f:facet name="header">Select</f:facet>
<h:selectOneRadio valueChangeListener="#{AddEntryMB.setSelectedItem}"
immediate="true" onchange="dataTableSelectOneRadio(this);">
<f:selectItem itemValue="null" />
</h:selectOneRadio>
</h:column>
<h:column>
<f:facet name="header">Last Name</f:facet>
#{c.lastName}
</h:column>
</h:dataTable>
</h:panelGrid>
<h:panelGroup>
<h:commandButton action="#{AddEntryMB.add}" value="add" />
<h:commandButton action="cancel" value="cancel" immediate="true"/>
</h:panelGroup>
And here is the backing bean.
#ManagedBean(name="AddEntryMB")
#ViewScoped
public class AddEntryMB implements Serializable {
private int rowIndex;
private int idValue;
private transient HtmlDataTable dataTable;
public void setSelectedItem(ValueChangeEvent event) {
rowIndex = dataTable.getRowIndex();
}
public void add()
{
DefaultScheduleEntry entry = new DefaultScheduleEntry();
entry.setId(RandomStringUtils.randomNumeric(32));
entry.setStartTime(from);
entry.setEndTime(until);
entry.setTitle(title);
entry.setSubtitle(location);
entry.setDescription(comments);
}

The view scoped bean will be recreated during every RESTORE_VIEW phase when you bind a component by binding to a property of the view scoped bean. This is known as JSF issue 1492 and fixed for the upcoming JSF 2.2.
In this particular case, you'd better remove binding="#{AddEntryMB.dataTable}" and grab the current var="c" from the EL context.
public void setSelectedItem(ValueChangeEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
DefaultScheduleEntry c = context.getApplication().evaluateExpressionGet(context, "#{c}", DefaultScheduleEntry.class);
// ...
}

Related

How to render a datatable in JSF with AJAX clicking a commandButton

The objective is to have a h:commandButton and once I have clicked it, using AJAX it will show the datatable "listaActores" (initially not showing it).
How could i do this? I have search for a solution, but I only found how to re-render the table once is present. My current code shows the table without doing nothing and clicking the button doesn't do anything.
<h:form>
<h:commandButton id="submit" value="Submit">
<f:ajax event="click" execute="#this" render="listaActores" />
</h:commandButton>
<h:dataTable id="listaActores" border="1"
value="#{peliculasEditarBean.listaActores}" var="actor">
<h:column>
<f:facet name="header">NOMBRE</f:facet>
#{actor.nombre}
</h:column>
<h:column>
<f:facet name="header">APELLIDO</f:facet>
#{actor.apellido}
</h:column>
</h:dataTable>
</h:form>
Your question is somewhat incomplete, but I'll answear anyway. Two things:
You're not saying how the table is "initially not showing". If there is some rendered on it, than you need to know that you must render a parent of the table. You can render only things that exist in rendered HTML. See for example this answer.
If you'll put action in the button you'll see that the AJAX won't work. You need to change event to action or delete this attribute to use a default.
I preperend simple working example (BTW. Welcome on Stackoverflow :-) If you want get help faster Minimal, Reproducible Example should be your's part of a question :-)):
(XHTML, added action to commandButton and remove event in f:ajax)
<h:form>
<h:commandButton id="submit" value="Submit"
action="#{peliculasEditarBean.initialize}">
<f:ajax execute="#this" render="listaActores" />
</h:commandButton>
<h:dataTable id="listaActores" border="1"
value="#{peliculasEditarBean.listaActores}" var="actor">
<h:column>
<f:facet name="header">NOMBRE</f:facet>
#{actor.nombre}
</h:column>
<h:column>
<f:facet name="header">APELLIDO</f:facet>
#{actor.apellido}
</h:column>
</h:dataTable>
</h:form>
(and bean)
#ManagedBean
#ViewScoped
public class PeliculasEditarBean implements Serializable {
private List<Actor> listaActores = null;
public List<Actor> getListaActores() {
return listaActores;
}
public void initialize() {
listaActores = new ArrayList<>(3);
listaActores.add(new Actor("foo", "bar"));
listaActores.add(new Actor("foo", "foo"));
listaActores.add(new Actor("bar", "bar"));
}
public class Actor {
private final String nombre;
private final String apellido;
Actor(String nombre, String apellido) {
this.nombre = nombre;
this.apellido = apellido;
}
public String getApellido() {
return apellido;
}
public String getNombre() {
return nombre;
}
}
}

Dynamic update primefaces component according to a autocomplete value

Someone can explain how to update an certain component in a view (example: dataScroller, dataList etc) using an autocomplete component ? I'm trying something with the ajax event "itemSelect" but with no success on how to proceed, any example, explanation, light will be a good help.
Some code (xhtml page)
<h:form id="frmPesquisarModalidade">
<p:autoComplete id="autoModalidade" multiple="true" value="#{matriculaBean.modalidadesSelecionadas}" completeMethod="#{matriculaBean.completeModalidade}"
var="modalidade" itemLabel="#{modalidade.nome}" itemValue="#{modalidade}" forceSelection="true">
<f:converter binding="#{modalidadeConverter}"/>
<f:ajax listener="#{matriculaBean.onItemSelect}" event="itemSelect" render="test"/>
<p:column style="width:10%">
<h:outputText value="#{modalidade.nome}"/>
</p:column>
</p:autoComplete>
<p:dataScroller id="dataScrollModalidadesSelecionadas" value="#{matriculaBean.modalidadesSelecionadas}" var="modalidade" chunkSize="6">
<h:panelGrid columns="2" cellpadding="5" id="test">
<h:outputText value="#{modalidade.nome}"/>
</h:panelGrid>
</p:dataScroller>
</h:form>
backing bean
#Named
#ViewScoped
public class MatriculaBean {
private List<Modalidade> modalidadesDisponiveis;
private List<Modalidade> modalidadesSelecionadas;
#Autowired
private ServicoModalidade servicoModalidade;
#PostConstruct
private void init(){
modalidadesDisponiveis = servicoModalidade.listar();
}
public List<Modalidade> completeModalidade(String busca) {
List<Modalidade> filtrados = new ArrayList<Modalidade>();
for (Modalidade mod : modalidadesDisponiveis) {
if (mod.getNome().contains(busca)) {filtrados.add(mod);}
}
return filtrados;
}
public void onItemSelect(SelectEvent event){
//????????
}
What you need to do in onItemSelect method is update the value of the target component, based on the selected item.
If you want to update dataScrollModalidadesSelecionadas:
public void onItemSelect(SelectEvent event){
//Get the selected item value
Modalidade m = new Modalidade();
m = event.getObject();
//Create/use a List method which can search the DB based on the selected item
modalidadesDisponiveis = servicoModalidade.listarPorModalidade(m);
}
And in the JSF, you just have to update the target component:
<p:autoComplete ...... >
<p:ajax listener="#{matriculaBean.onItemSelect}" event="itemSelect" update="dataScrollModalidadesSelecionadas"/>
</p:autoComplete>
I'm not sure if those options and properties you defined gonna work as expected, but the example above is the basics to update a component based on ItemSelect.
Also, I prefer using <p:ajax> rather than <f:ajax>
<h:form id="frmPesquisarModalidade">
<p:autoComplete id="autoModalidade" multiple="true" value="#{matriculaBean.modalidadesSelecionadas}" completeMethod="#{matriculaBean.completeModalidade}"
var="modalidade" itemLabel="#{modalidade.nome}" itemValue="#{modalidade}" forceSelection="true">
<f:converter binding="#{modalidadeConverter}"/>
<p:ajax event="itemSelect" update="dataScrollModalidadesSelecionadas"/>
<p:column style="width:10%">
<h:outputText value="#{modalidade.nome}"/>
</p:column>
</p:autoComplete>
<p:dataScroller id="dataScrollModalidadesSelecionadas" value="#{matriculaBean.modalidadesSelecionadas}" var="modalidade" chunkSize="6">
<h:panelGrid columns="2" cellpadding="5">
<h:outputText value="#{modalidade.nome}"/>
</h:panelGrid>
</p:dataScroller>
</h:form>
solved!!! to resolve my issue i'd discovered theres no need to apply an backing bean logic withe the itemSelect event... just create an ajax event in the xhtml page and use the update attribute with the respective id! Thanks for help

jsf inputText only displayed value when is readonly true or outputText

I have a h:inputText with valueChangeListener, when the user type some code another h:inputText display data from MySQL about that code, the valueChangeListener works but the second h:inputText not displayed the value and only do it when I set the readonly attribute or I change the component to h:outputText
my facelets page is:
<h:form id="idFacturacion">
<rich:panel>
<f:facet name="header">
<h:outputText value="FACTURACION AL CLIENTE" />
</f:facet>
<h:panelGrid columns="4">
<h:outputText value="Cedula: " />
<h:inputText value="#{facturaBean.encFactura.cedula}" onchange="submit();" valueChangeListener="#{facturaBean.processValueChange}" />
<h:outputText value="Nombre: " />
<h:inputText value="#{facturaBean.encFactura.nombre_cli}" />
</h:panelGrid>
</rich:panel>
</h:form>
facturaBean is:
#ManagedBean
#SessionScoped
public class FacturaBean {
private EncFactura encFactura = new EncFactura();
//getter and setter
public void processValueChange(ValueChangeEvent event){
String ced = event.getNewValue().toString();
try{
//do the database thing
if(resultSet.next()){
encFactura.setNombre_cli(resultSet.getString("nombre_cli"));
}else{
encFactura.setNombre_cli("");
}
}catch(SQLException error){
facesContext.addMessage(null, new FacesMessage("Hubo un error SQL."));
}
}
}
Please see
Change inputText value from listener method… and
Possible to execute `valueChangeListener` for `p:inputText` without hitting `enter` key?
May I suggest using ajax?
Here is a primefaces example but you could apply to richfaces..
<h:inputText value="#{facturaBean.stringOne}" >
<p:ajax event="change" listener="#{facturaBean.processValueChange}" update="strTwo"/> </h:inputText> <h:outputText value="Nombre: " />
<h:inputText id="strTwo" value="#{facturaBean.stringTwo}" />
</h:panelGrid>
private String stringOne= "";
private String stringTwo= "";
public void processValueChange(){
stringTwo = stringOne;
}
With getters etc.. basically on change, fires off to ajax, you do your database call etc, then it returns the response and updates your other input field, it's a much cleaner way than trying to submit forms etc..
Also are you sure you want session scope?

Primefaces binding Bean with form

I'm developing an application with primefaces, I´m trying to map my form with my Bean of User but i can't, this is my code:
<h:form>
<p:panelGrid columns="2">
<h:outputLabel for="usuario" value="Usuario: *"/>
<h:inputText id="usuario" binding="#{beanPrueba.user.usuario}"></h:inputText>
<h:outputLabel for="contrasena" value="Contraseña: *" />
<h:inputSecret id="contrasena"></h:inputSecret>
<f:facet name="footer">
<p:commandButton icon="ui-icon-check" value="Entrar" ajax="false"
action="#{beanPrueba.prueba()}"/>
</f:facet>
</p:panelGrid>
</h:form>
Backing bean:
#ManagedBean(name = "beanPrueba")
#SessionScoped
public class BeanLogin {
private Usuario user = new Usuario();
public Usuario getUser() {
return user;
}
public void setUser(Usuario user) {
this.user = user;
}
public void prueba()
{
try {
//my code
}
catch(Exception ex)
{
System.out.print(ex.getMessage());
}
}
in my bean declare a object of User, I'm using the object user for map my form with my bean but I get an error when map to bean with my form
You are using binding attribute completely wrong. In your case you shouldn't use binding, replace it with value attribute. binding is used if you want to bind whole component with some UIComponent property of your backing bean, and manage component attributes programmatically. Value provide connection between component value, and some backing bean property.
I think it's also wrong the syntax of method calling, it should be
<p:commandButton icon="ui-icon-check" value="Entrar" ajax="false"
action="#{beanPrueba.prueba}"/>
without parenthetis.

JSF Cannot set the current variable entity in the managed bean in order to understand which entity has been selected by the user

Im trying to implement the modification of an entity in JSF using Primefaces.
My main view, which lists the users is the following:
<p:growl id="growlEditUnit" showDetail="true" life="12000" />
<p:dialog id="dialogEditUnit" header="Edit Unit" widgetVar="editUnitDialog" showEffect="fade" hideEffect="fade" resizable="false" >
<ui:include src="editUnit.xhtml" />
</p:dialog>
<h:form id="form2">
<p:dataTable id="units" var="unit" value="#{unitController.unitsOfLoggedInUser}" >
<f:facet name="header">
Click Edit or Delete after selecting a unit to modify or remove it
</f:facet>
<p:column headerText="Code">
#{unit.unitCode}
</p:column>
<p:column headerText="Name">
#{unit.unitName}
</p:column>
<p:column headerText="Semester" >
#{unit.semester}
</p:column>
<p:column headerText="Academic Year">
#{unit.academicYear}
</p:column>
<p:column headerText="Twitter Username">
#{unit.twitterUsername}
</p:column>
<p:column headerText="Actions">
<p:commandButton id="editButton" value="Edit" action="#{unitController.setCurrent(unit)}" update=":dialogEditUnit" oncomplete"editUnitDialog.show()" />
</p:column>
</p:dataTable>
</h:form>
This view lists all the data correctly. However, when I press the current, my aim is to set the current attribute of the managed bean (code listed below) with the unit based on the button clicked. After this I try to update the edit dialog, so it will be filled with the values of that unit, and then make it visible using the oncomplete attribute. However, it seems that the managed been method setCurrent(unit) is never called when clicking the edit button. Subsequently the dialog is shown empty. Can someone help me with what am I doing wrong?
I am posting the managed bean code too.
#ManagedBean(name = "unitController")
#ViewScoped
public class UnitController implements Serializable {
private Unit current;
private List<Unit> unitsOfLoggedInUser;
#ManagedProperty(value="#{loginController.checkedUser}")
private Lecturer lecturer;
#EJB
private web.effectinet.ejb.UnitFacade ejbFacade;
#EJB
private web.effectinet.ejb.LecturerFacade lecturerFacade;
public UnitController() {
}
#PostConstruct
public void init(){
if (lecturer.getLecturerId() == null)
unitsOfLoggedInUser = null;
else
unitsOfLoggedInUser = (List<Unit>) lecturer.getUnitCollection();
}
public List<Unit> getUnitsOfLoggedInUser() {
return unitsOfLoggedInUser;
}
public void setCurrent(Unit current) {
this.current = current;
}
public Lecturer getLecturer() {
return lecturer;
}
public void setLecturer(Lecturer lecturer) {
this.lecturer = lecturer;
}
The action attribute of the commandButton is rendered without information on the value of the unit variable.
To pass the unit to the action method of your managed bean, then you need to pass the ID of unit in an <f:param> child tag of commandButton.
<p:commandButton action="#{managedBean.actionMethod}" ........>
<f:param name="unitid" value="#{unit.id}" />
</p:commandButton>
From your action method you can get the request parameter by the name from the ExternalContext and this will give you the ID of the unit that the commandButton was pressed for in your dataTable.

Resources