How to remove a row <h:datatable> programmatically - jsf

I have a form like the following picture.
In the above picture you can see a green add button. When I click on it, it create a new row in a datatable via send a <f:ajax> to backing bean and render <h:datatable>.
Until now all thing is good. But i Except when I click on a cross button inside of each row, that row removed. but it have a bug. for example when I click on the third row cross button, it removes this row from backing bean but not from my ui.
in the following you can see my backing bean and .xhtml file.
#ManagedBean(name = "AddPollContorler")
#ViewScoped
public class AddPollControl {
private List<Answer> answers = new ArrayList<Answer>();
#PostConstruct
public void init(){
answers.add(new Answer());
answers.add(new Answer());
}
public List<Answer> getAnswers() {
return answers;
}
public void setAnswers(List<Answer> answers) {
this.answers = answers;
}
public void addAnswer() {
answers.add(new Answer());
}
public void removeAnswer() {
String index=FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("index");
if (StringUtil.isNumber(index))
answers.remove(Integer.parseInt(index));
}
}
.xhtml :
<div class="panel panel-success rgt">
<div class="panel-heading rgt">
<div style="float: left;">
<h:commandLink styleClass="btn btn-success table-button" action="#{AddPollContorler.addAnswer}">
<h:graphicImage library="img" name="add.png" styleClass=" table-icon" />
<f:ajax execute="answers" render="answers"></f:ajax>
</h:commandLink>
</div>
<h4><h:outputText value="#{msg['protected.poll.add.answers']}"/></h4>
</div>
<div class="form-margin">
<h:dataTable value="#{AddPollContorler.answers}" var="answer" id="answers" style="width:100%;">
<h:column >
<div class="input-group poll-answer" style="margin: 5px;">
<span class="input-group-addon no-left-radius"><h:outputText value="#{CounterControler.index+1}" /></span>
<h:inputText value="#{answer.text}" styleClass="form-control no-radius"/>
<div class="input-group-addon no-right-radius poll-answer-remove" >
<h:commandLink action="#{AddPollContorler.removeAnswer}">
<h:graphicImage library="img" name="cross.png" />
<f:param name="index" value="#{CounterControler.last}" />
<f:ajax render="answers answers" />
</h:commandLink>
</div>
</div>
</h:column>
</h:dataTable>
</div>
</div>
update: 2013/06/12
#ManagedBean(name="CounterControler")
public class CounterControl {
private int index=0;
public int getIndex(){
return index++;
}
public int getLast(){
return index-1;
}
}

your code does look pretty good already. How does the CounterControler internally work? (no source given) Alternatives to send the current object might be
to give the object directly as the parameter (you need a fitting converter for that),
give it as direct parameter (action="#{AddPollContorler.removeAnswer(answer)}, works from EL 2.2 on), or
directly get the current object out of the given ActionEvent
The last point would look like
xhtml
<h:commandLink action="#{AddPollContorler.removeAnswer}">
<h:graphicImage library="img" name="cross.png" />
<f:ajax render="answers" />
</h:commandLink>
managed bean
public void removeAnswer(ActionEvent ev) {
Answer selectedItem = null;
try {
UIDataTable objHtmlDataTable = retrieveDataTable(
(UIComponent)ev.getSource());
selectedItem = (Answer) objHtmlDataTable.getRowData();
answers.remove(answer);
} catch (NullPointerException e) {
// somehow couldn't find the element
}
}
private static UIDataTable retrieveDataTable(UIComponent component) {
if (component instanceof UIDataTable) {
return (UIDataTable) component;
}
if (component.getParent() == null) {
return null;
}
return retrieveDataTable(component.getParent());
}
I like that one because it takes most logic out of the frontend. Hope you get your rows cleaned with one of that tactics.
Also, you only need to mention answers once in <f:ajax render="answers" />
EDIT: Even I don't know why - wrapping a <h:panelGroup layout="block" id=" answersWrapper"> around the <h:dataTable> and rendering that panelGroup worked for me.
<h:form id="myForm">
<h:panelGroup id="answerWrapper" layout="block">
<rich:dataTable value="#{myTestBean.answers}" var="answer" id="answers">
<h:column >
<h:outputText value="#{answer}"/>
<h:commandButton id="button" action="#{myTestBean.doTheAction}">
<f:ajax render=":myForm:answerWrapper" />
</h:commandButton>
</h:column>
</rich:dataTable>
</h:panelGroup>
</h:form>

Related

Redirect to an other page or show a dialog message if something went wrong

Currently developping a Java8 web app with JSF and primefaces, and I am succeeding in posting a new form with an Oracle Database. But I think, if there is an error for a reason or another, I would like to inform the user by, instead of redirecting him to another page, just showing him a dialog and say something like "something went wrong, try again later".
So is it possible ? I think I have to combine the following commandButton that output a dialog message with the other commandButton in my form.xhtml. But action and onclick a note compatible, aren't they?
Edit : a growl message could also fit if it is easier
<p:commandButton value="Valider l'enquête" type="button" onclick="PF('dlg2').show();" icon="fa fa-plus-circle"/>
<p:dialog header="Modal Dialog" widgetVar="dlg2" modal="true" height="100">
<h:outputText value="This is a Modal Dialog." />
</p:dialog>
form.xhtml
<h:form>
<div id="postFormulaire" class="ui-g">
<div class="ui-g-5"></div>
<p:selectOneMenu id="comiteMenu" value="#{enquete.idComite}">
<f:selectItems value="#{sessionScope.utilisateur.comites}" var="comite" itemLabel="#{comite}" itemValue="#{comite.idComite}" />
</p:selectOneMenu>
<div class="ui-g-5"></div>
<ui:repeat id="repeater" value="#{enquete.questionsReponses}" var="questResp" class="ui-g-12">
<div class="ui-g-12"><b>#{questResp.question.titreQuestion}</b> #{questResp.question.question} </div>
<div class="ui-g-1"/>
<p:inputTextarea class="ui-g-9" id="reponse" value="#{questResp.reponse.commentaire}" label="f"></p:inputTextarea>
<div class="ui-g-2"/>
<div class="ui-g-2"/><p:separator id="separator" class="ui-g-8" /><div class="ui-g-2"/>
</ui:repeat>
<div class="ui-g-5"/><p:commandButton id="validerForm" class="ui-g-2" icon="fa fa-plus-circle" value="Valider l'enquête"
action="#{enquete.postNewForm()}" process="#form"></p:commandButton><div class="ui-g-5"/>
</div>
</h:form>
#Named
#RequestScoped
public class Enquete implements Serializable {
private List<QuestionReponse> questionsReponses;
private int idUser;
private int idComite;
#PostConstruct
private void init() {
questionsReponses = new ArrayList<>();
List<Question> questions = EnqueteDAO.loadQuestions();
for(int i=0; i< questions.size();i++) {
this.questionsReponses.add(new QuestionReponse(questions.get(i), new Reponse(questions.get(i).getIdQuestion())));
}
}
//validate form
public String postNewForm() {
boolean success = EnqueteDAO.create(questionsReponses, idComite); // this method will return a boolean true if the request has succeeded and false if it did not
return (success ? "../admin.xhtml?faces-redirect=true" : "#" ); //if it succeeded but what to return if not
}
}

JSF CommandButton action not invoked (another example)

I took the example from https://stackoverflow.com/a/3180885/242042 just tweaked it for my needs.
Here's my bean:
#ManagedBean
#ViewScoped
public class ParticipantBean implements
Serializable {
private boolean edit;
private List<Participant> list;
private Participant participant = new Participant();
#Inject
private transient ParticipantDAO participantDAO;
public void add() {
System.out.println("Calling add");
participantDAO.save(participant);
init();
}
public void delete(final Participant participant) {
participant.getAudit().cancel();
participantDAO.save(participant);
init();
}
public void edit(final Participant participant) {
this.participant = participantDAO.get(participant.getId());
edit = true;
}
public void fire() {
System.out.println("fired");
}
public List<Participant> getList() {
return list;
}
public Participant getParticipant() {
return participant;
}
#PostConstruct
public void init() {
list = participantDAO.getAll();
participant = new Participant(); // Reset placeholder.
}
public boolean isInEdit() {
return edit;
}
public void saveParticipant() {
System.out.println("Calling save");
participantDAO.save(participant);
System.out.println("Done Calling save");
init();
edit = false;
}
}
And my JSF file
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Really simple CRUD</title>
</h:head>
<h:body>
<h3>List items</h3>
<h:form rendered="#{not empty participantBean.list}">
<h:dataTable value="#{participantBean.list}" var="item">
<h:column><f:facet name="header">ID</f:facet>#{item.id}</h:column>
<h:column><f:facet name="header">Name</f:facet>#{item.name}</h:column>
<h:column><h:commandButton value="edit" action="#{participantBean.edit(item)}" /></h:column>
<h:column><h:commandButton value="delete" action="#{participantBean.delete(item)}" /></h:column>
<h:column><h:commandButton value="fire" action="#{participantBean.fire}" /></h:column>
</h:dataTable>
</h:form>
<h:panelGroup rendered="#{empty participantBean.list}">
<p>Table is empty! Please add new items.</p>
</h:panelGroup>
<h:panelGroup rendered="#{!participantBean.inEdit}">
<h3>Add item</h3>
<h:form>
<p>Name: <h:inputText value="#{participantBean.participant.name}" /></p>
<p><h:commandButton value="add" action="#{participantBean.add}" /></p>
<p><h:commandButton value="fire" action="#{participantBean.fire}" /></p>
</h:form>
</h:panelGroup>
<h:panelGroup rendered="#{participantBean.inEdit}">
<h3>Edit item #{participantBean.participant.id}</h3>
<h:form>
<p>Name: <h:inputText value="#{participantBean.participant.name}" /></p>
<p><h:commandButton value="save" action="#{participantBean.saveParticipant}" /></p>
<p><h:commandButton value="add" action="#{participantBean.add}" /></p>
<p><h:commandButton value="fire" action="#{participantBean.fire}" /></p>
</h:form>
</h:panelGroup>
</h:body>
</html>
So it is quite similar, but what I don't understand is why on the "edit" it does not want to invoke the actions. (i.e. I don't see anything on SystemOut.log)
I was looking at the answer https://stackoverflow.com/a/13327382/242042 to see if there was anything to merit it, but I found that the "System.out.println()" events do not even get fired. The control is there.
One thing I did notice was the commandButtons reload the screen while inEdit
I have eliminated "Prime Faces" as well and I am testing on WebSphere 9.0.0.3. The code is in https://github.com/trajano/jee/tree/no-prime-faces
I also have tried reordering the form such that the edit block is in the form like so but it still the actions do not fire.
<h:form rendered="#{not empty participantBean.list}">
<h:dataTable value="#{participantBean.list}" var="item">
<h:column><f:facet name="header">ID</f:facet>#{item.id}</h:column>
<h:column><f:facet name="header">Name</f:facet>#{item.name}</h:column>
<h:column><h:commandButton value="edit" action="#{participantBean.edit(item)}" /></h:column>
<h:column><h:commandButton value="delete" action="#{participantBean.delete(item)}" /></h:column>
</h:dataTable>
<h:panelGroup rendered="#{participantBean.inEdit}">
<h3>Edit item #{participantBean.participant.id}</h3>
<p>Name: <h:inputText value="#{participantBean.participant.name}" /></p>
<p><h:commandButton value="save" action="#{participantBean.saveParticipant}" /></p>
<p><h:commandButton value="add" action="#{participantBean.add}" /></p>
</h:panelGroup>
</h:form>
I also tried having edit() written this way to get the participant that was on the original list that way it will have the proper optimistic lock #Version
public void edit(final Participant participant) {
this.participant = participant;
edit = true;
}
In JSF 2.2 there are two annotations in different packages named #ViewScoped
javax.faces.bean.ViewScoped ← correct one
javax.faces.view.ViewScoped ← incorrect one introduced with JSF 2.2 (which was what I was using when I wrote the question)
To limit it to JSF 2.2 as per #Jasper de Vries 's comment. The annotations need to change to
#javax.inject.Named
#javax.faces.view.ViewScoped

Toggle images using ajax

I have 4 buttons, each button will display one image using Ajax.
<h:form>
<h:commandButton value="Click" action="#{userAjaxData.toggleStatus}">
<f:ajax render="Family" />
</h:commandButton>
<h:commandButton value="Click" action="#{userAjaxData.toggleStatus}">
<f:ajax render="Karam"/>
</h:commandButton>
<h:commandButton value="Click" action="#{userAjaxData.toggleStatus}">
<f:ajax render="Memo"/>
</h:commandButton>
<h:commandButton value="Click" action="#{userAjaxData.toggleStatus}">
<f:ajax render="Baba"/>
</h:commandButton>
<h:panelGroup id="Family">
<p:graphicImage library="images/img" name="family.png" id="FamilyImg" rendered="#{userAjaxData.status}"/>
</h:panelGroup>
<h:panelGroup id="Karam">
<p:graphicImage library="images/img" name="Karam.png" id="KaramImg" rendered="#{userAjaxData.status}"/>
</h:panelGroup>
<h:panelGroup id="Memo">
<p:graphicImage library="images/img" name="memo.png" id="MemoImg" rendered="#{userAjaxData.status}"/>
</h:panelGroup>
<h:panelGroup id="Baba">
<p:graphicImage library="images/img" name="baba.png" id="BabaImg" rendered="#{userAjaxData.status}"/>
</h:panelGroup>
</h:form>
My manged bean:
#ManagedBean(name = "userAjaxData", eager = true)
#SessionScoped
public class UserAjaxData implements Serializable {
private static final long serialVersionUID = 1L;
private boolean status = false;
public void toggleStatus() {
status = true;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}}
when I click any button It will display the related image, so if I click the first one it will display the first image, and the second button will display the second image but the first image will not removed. I just need one way to display one image each time I click button. so if I click the first button then the second button should the second image displayed and the first one disappear.
How can I mange it?
If your usecase is really that simple, I would recommend using only one always rendered <h:graphicImage /> (no need for PrimeFaces GraphicImage in this case) and set the appropriate image to show in the backing bean via ajax instead of one or multiple toggle statuses with something like this:
<h:form id="form">
<h:commandButton
id="familyButton"
action="#{toggleImageView.setImage('family.png')}"
value="Family"
>
<f:ajax render="image" />
</h:commandButton>
<h:commandButton
id="karamButton"
action="#{toggleImageView.setImage('karam.png')}"
value="Karam"
>
<f:ajax render="image" />
</h:commandButton>
<h:commandButton
id="memoButton"
action="#{toggleImageView.setImage('memo.png')}"
value="Memo"
>
<f:ajax render="image" />
</h:commandButton>
<h:commandButton
id="babaButton"
action="#{toggleImageView.setImage('baba.png')}"
value="Baba"
>
<f:ajax render="image" />
</h:commandButton>
<br />
<h:graphicImage
id="image"
library="image/img"
name="#{toggleImageView.image}"
/>
</h:form>
#ManagedBean
#RequestScoped
public class ToggleImageView {
private String image;
#PostConstruct
public void initialize() {
image = "family.png";
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
}
Just adapt to your needs.

'omnifaces.SelectItemsConverter' converter id is not registered

I'm trying to create a selectManyCheckbox feature in my application, but now I'm in "converter problem". To take care this, I'm trying to use Omnifaces that already have a converter to objects.
My solution is based on this and this question (both answered by BalusC).
Don't know if it helps, but he is my view code:
<h:selectManyCheckbox style="margin-bottom: 40px;" id="disciplinas" value="#{cursoMBean.listaDisciplinasDoCurso}" converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{cursoMBean.listaTodasDisciplinas}" var="disciplina" itemValue="#{disciplina}" itemLabel="#{disciplina.nome}"/>
</h:selectManyCheckbox>
And my MBean:
private static ArrayList<Disciplina> listaTodasDisciplinas;
private static ArrayList<Disciplina> listaDisciplinasDoCurso;
public ArrayList<Disciplina> getListaTodasDisciplinas() {
return listaTodasDisciplinas;
}
public void setListaTodasDisciplinas(
ArrayList<Disciplina> listaTodasDisciplinas) {
CursoMBean.listaTodasDisciplinas = listaTodasDisciplinas;
}
public ArrayList<Disciplina> getListaDisciplinasDoCurso() {
return listaDisciplinasDoCurso;
}
public void setListaDisciplinasDoCurso(
ArrayList<Disciplina> listaDisciplinasDoCurso) {
CursoMBean.listaDisciplinasDoCurso = listaDisciplinasDoCurso;
}
Disciplina:
public class Disciplina {
private int id;
private String nome;
public Disciplina(int id, String nome) {
this.id = id;
this.nome = nome;
}
public Disciplina() {
}
// Methods
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
if (!(nome.isEmpty() || nome == " " || nome == " ")){
this.nome = nome;
}
}
#Override
public String toString() {
return nome;
}
}
My problem is: this actually don't works. When I select some checkbox and submit, this create a new Curso but the arraylist of selected Disciplina still empty. I think the problem is that JSF can't find Omnifaces converter. This is my HTML tag in view:
<html xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:o="http://omnifaces.org/ui"
xmlns:of="http://omnifaces.org/functions">
When I hover the "converter" in selectManyCheckbox appears a warning:
'omnifaces.SelectItemsConverter' converter id is not registered.
I putted the Omnifaces JAR inside Web-Inf/lib. To me, everything is okay, why Omnifaces don't populate my ArrayList with the selected items?
Edit
This is the button to submit the form with the checkboxes:
<h:commandButton id="enviar" styleClass="btn btn-lg btn-success pull-right" value="Adicionar" action="#{cursoMBean.cadastrar}">
<f:ajax event="click" onevent="insert.hide()" render=":meuForm:minhaTabela"
listener="#{cursoMBean.cadastrar}" />
</h:commandButton>
And here is the called method:
public String cadastrar() {
Curso curso = new Curso();
System.out.println("Check if listaDisciplinasDoCurso have something inside): " + listaDisciplinasDoCurso.size() +"\n");
for (Disciplina d : listaDisciplinasDoCurso) {
System.out.println(d);
}
if (!(this.getNome().isEmpty() || this.getNome() == " " || this
.getNome() == " ")) {
curso.setNome(this.getNome());
// Clearing the listaDisciplinasDoCurso
listaDisciplinasDoCurso = new ArrayList<Disciplina>();
// Adding course to database
controleCurso.adicionar(curso);
System.out.println("Inserted. " + curso.toString());
} else {
System.out.println("Error: Not inserted. " + curso.toString());
}
limparCampos();
atualizarListagem();
return null;
}
Edit 2
My newest code, with two forms:
<h:form id="inserirDisciplina">
<div class="form-group">
<div class="col-md-10">
<h:inputText styleClass="form-control" id="disciplina" value="#{cursoMBean.nome}" valueChangeListener="#{cursoMBean.atualizarListagemPesquisa}">
<f:ajax event="keyup" render=":meuForm:minhaTabela" />
</h:inputText>
</div>
<div class="col-md-2">
<h:commandButton value="Adicionar" styleClass="btn btn-md btn-success" process="disciplina" partialSubmit="true">
<p:ajax event="click" update=":meuForm:display" render=":meuForm:dialog" partialSubmit="true" process="disciplina" oncomplete="PF('insert').show();" onerror="alert('erro');" />
</h:commandButton>
</div>
</div>
</h:form>
<p:messages autoUpdate="true" />
<p:dialog id="dialog" header="Inserir Curso" widgetVar="insert"
resizable="false" modal="true" width="600" height="500"
hideEffect="clip" closeOnEscape="true">
<h:form>
<h:panelGrid id="display" styleClass="col-lg-10 center" style="margin-top: 10px; margin-bottom: 15px;">
<label for="nome">Nome:</label>
<p:inputText styleClass="form-control adicionar" id="nome" value="#{cursoMBean.nome}">
</p:inputText>
</h:panelGrid>
<h:panelGrid styleClass="col-lg-10 center">
<p:columnGroup>
<label for="disciplinas">Disciplinas do Curso:</label>
<h:selectManyCheckbox style="margin-bottom: 40px;" id="disciplinas" value="#{cursoMBean.listaDisciplinasDoCurso}" converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{cursoMBean.listaTodasDisciplinas}" var="disciplina" itemValue="#{disciplina}" itemLabel="#{disciplina.nome}" />
</h:selectManyCheckbox>
</p:columnGroup>
</h:panelGrid>
<h:panelGrid styleClass="col-lg-10 center">
<p:columnGroup>
<h:commandButton id="enviar" styleClass="btn btn-lg btn-success pull-right" value="Adicionar" action="#{cursoMBean.cadastrar}">
<f:ajax event="click" execute="#form" onevent="insert.hide()" render=":meuForm:minhaTabela" listener="#{cursoMBean.cadastrar}" />
</h:commandButton>
</p:columnGroup>
</h:panelGrid>
</h:form>
</p:dialog>
As to the Eclipse warning mentioned in the title,
'omnifaces.SelectItemsConverter' converter id is not registered
just ignore it. It's actually registered via a #FacesConverter annotation. It's only the IDE who's not smart enough to detect the #FacesConverter annotated classes in JARs deployed in /WEB-INF/lib. It's only looking for <converter> entries in faces-config.xml. Try to actually run the webapp project. If the converter wasn't properly registered, then you should have gotten the following exception:
javax.faces.FacesException: Expression Error: Object named: omnifaces.SelectItemsConverter not found
Coming back to your concrete problem, those static properties aren't right. Remove those static modifiers. Also, the <f:ajax> executes by default the current component, as in
<f:ajax execute="#this">
You need to specify it to #form if you intend to execute the entire form
<f:ajax execute="#form">
Also, the onevent="insert.hide()" is wrong. The onevent attribute should point to a function reference, not perform a function call. The function reference is in turn called three times per ajax request. Just use <h:commandButton onclick> for that instead.
Unrelated to the concrete problem, also get rid of event="click" it's the default already. There's no need to repeat the defaults.

h:inputText data cached

Click "LINK1" --> modal popsup --> enter value in text-box --> click Submit/Process
Click another link "update/cancel" --> same modal popsup --> I see the value in the text box (This is fine and if I reload the page and click the link again, the modal appears with values intact)
Click "LINK1" --> same modal popsup --> I see the value in the text box cached(this time I want the values not to be cached in the text box) --> If I reload the page, the values go away though.
I have tried clearing the backing-bean when the links are clicked, but still the values appear. Please advise.
Update here is the code:
ReimbursementActionBean.java
#Name("reimbursementAction")
#Scope(ScopeType.CONVERSATION)
public class ReimbursementActionBean implements Serializable {
public void initReimbursement(PaymentInfo payment) {
// do something
}
public void initNewReimbursement(PaymentInfo payment) {
initReimbursement(payment);
// --> log.info("CLEARING INPUT ELEMENT CACHE");
// -->this.getReimbursement().setAmount(null);
hideModal = false;
}
public void initUpdateReimbursement(PaymentInfo payment) {
initReimbursement(payment);
hideModal = false;
}
public void initCancelReimbursement(PaymentInfo payment) {
initReimbursement(payment);
hideModal = true;
}
public void reimbursePayment() {
// do something
}
public void updateReimbursment() {
// do something
}
public void cancelReimbursment() {
// do something
}
public void cancelupdateReimbursment() {
hideModal = true;
}
public Reimbursement getReimbursement() {
return reimbursement;
}
public void setReimbursement(Reimbursement reimbursement) {
this.reimbursement = reimbursement;
}
}
reimbursePaymentModal.xhtml
< rich:modalPanel id="reimbursePaymentPanel"
width="430"
autosized="true"
showWhenRendered="#{!hideModal}">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="Reimburse Payment"/>
</h:panelGroup>
</f:facet>
<h:form>
<a4j:outputPanel id="reimbursePaymentDiv">
<s:div styleClass="section" style="padding:5px;padding-left:0px;">
<s:decorate template="/layout/edit.xhtml">
<ui:define name="label">Reimbursement Amount(*)</ui:define>
<h:inputText id="reimbursementAmount"
value="#{reimbursementAction.reimbursement.amount}">
<a4j:support event="onblur" rerender="reimbursementAmount" action="#{reimbursementAction.validateAmount}" limitToList="true" />
</h:inputText>
</s:decorate>
<div style="clear:both"></div>
</s:div>
<div class="button-holder" style="padding-top:10px">
<div style="float:right">
<a4j:commandLink oncomplete="Richfaces.hideModalPanel('reimbursePaymentPanel');"
immediate="true"
action="#{reimbursementAction.cancelupdateReimbursment()}"
styleClass="button"
reRender="reimbursePaymentPanel">
<!--todo add cancel command to reimbursementAction-->
<span class="inner-button">Cancel</span>
</a4j:commandLink>
</div>
<div style="float:right">
<a4j:commandLink id="reimbursePaymentId" styleClass="button"
oncomplete="this.disabled=false;"
action="#{reimbursementAction.reimbursePayment}"
rendered="#{reimbursementAction.reimbursementConstraints.allowableReimbursementAction eq 'SUBMIT_NEW'}"
reRender="paymentSearchResults,reimbursePaymentDiv,reimbursePaymentPanel,pnlInfoView" limitToList="true"
bypassUpdates="true" onclick="this.disabled=true;">
<span class="inner-button">Process</span>
</a4j:commandLink>
</div>
</div>
</a4j:outputPanel>
</h:form>
</rich:modalPanel>
PaymentList.xhtml
< a4j:outputPanel id="paymentSearchResults" ajaxRendered="true">
<s:div styleClass="section" style="overflow-y:scroll; overflow-x:hidden;max-height:420px;margin:10px "
rendered="#{not empty paymentList}">
<rich:dataTable id="paymentListId"
var="payment"
value="#{paymentList}"
styleClass="data-table"
rowClasses="odd,even"
width="100%">
<!-- Reimburse -->
<s:div rendered="#{payment.reimbursementSummary.allowableReimbursementActionType eq 'SUBMIT_NEW'}">
<a4j:commandLink action="#{reimbursementAction.initNewReimbursement(payment)}"
reRender="reimbursePaymentPanel,reimbursePaymentDiv"
limitToList="true">
<span> Reimburse</span>
</a4j:commandLink>
</s:div>
<!-- Update Reimburse and Cancel Reimbursement-->
<s:div rendered="#{payment.reimbursementSummary.allowableReimbursementActionType eq 'MODIFY_EXISTING'}">
<a4j:commandLink action="#{reimbursementAction.initUpdateReimbursement(payment)}"
reRender="reimbursePaymentPanel,reimbursePaymentDiv"
limitToList="true"
bypassUpdates="true">
<span>Update Reimbursement</span>
</a4j:commandLink>
<h:outputText value=" | "/>
<a4j:commandLink oncomplete="Richfaces.showModalPanel('cancelReimbursementPanel');"
action="#{reimbursementAction.initCancelReimbursement(payment)}"
reRender="cancelReimbursementDiv"
limitToList="true">
<span>Cancel Reimbursement</span>
</a4j:commandLink>
</s:div>
</div>
</rich:column>
</rich:dataTable>
</s:div>
</a4j:outputPanel>
The links I am talking about are: Reimburse and Update Reimbursement. Clicking on the links rerender reimbursePaymentPanel which open up the modal with id=reimbursePaymentPanel having textbox with id="reimbursementAmount".
I think you should add in the reRender of your a4j:commandLink the id of the text box that you wanna update, which is "reimbursementAmount":
<a4j:commandLink
action="#reimbursementAction.initNewReimbursement(payment)}"
reRender="reimbursePaymentPanel,reimbursePaymentDiv,**reimbursementAmount**"
limitToList="true">
<span>Reimburse</span>
</a4j:commandLink>
If this didn't work, try to include the modalPanel on the same page, which is "PaymentList.xhtml".
HTH.
Here is what I tried that worked.
reimbursePaymentModal.xhtml
<s:decorate template="/layout/edit.xhtml">
<ui:define name="label">Reimbursement Amount(*)</ui:define>
<h:inputText id="reimbursementAmount"
binding="#{reimburseEvent.amountText}"
value="#{reimbursementAction.reimbursement.amount}">
<a4j:support event="onblur" action="#{reimbursementAction.validateAmount}"
limitToList="true"/>
</h:inputText>
</s:decorate>
PaymentList.xhtml
<s:div rendered="#{payment.reimbursementSummary.allowableReimbursementActionType eq 'SUBMIT_NEW'}">
<a4j:commandLink action="#{reimbursementAction.initNewReimbursement(payment)}"
reRender="reimbursePaymentPanel,reimbursePaymentDiv, reimbursementAmount"
actionListener="#{reimbursementAction.clearForm}" immediate="true" limitToList="true"
>
<span> Reimburse</span>
</a4j:commandLink>
</s:div>
ReimbursementActionBean.java
#In(required=false)
private ReimburseEvent reimburseEvent;
//Added
public void clearForm(ActionEvent event){
if(reimbursement!=null){
reimbursement.setAmount(null);
getReimbursement().setAmount(null);
}
reimburseEvent.getAmountText().setSubmittedValue("");
}
ReimburseEvent.java
#Name("reimburseEvent")
#Scope(ScopeType.EVENT)
#AutoCreate
public class ReimburseEvent {
// amountText is binding attribute in the reimbursementPaymentModal. Binding attributes cannot be used in ReimbursementActionBean (Since it is Conversation Scope).
// So creating ReimburseEvent (Event scope) to support the binding attribute and injecting it to ReimbursementActionBean.
private UIInput amountText;
public void setAmountText(UIInput amountText) {
this.amountText = amountText;
}
public UIInput getAmountText() {
return amountText;
}
}

Resources