Capturing primefaces <p:autoComplete> change event (detect emptying) - jsf

i got a question concerning an Primefaces autocomplete. Rigth now i am updating a field with the value of a property of the selected value in the autocomplete, like this:
This is in my xhtml:
<p:autoComplete
value="#{trFitoModel.selectedProducte}"
id="nomComercial"
completeMethod="#{trFitoBacking.completeProducte}"
var="producte" itemLabel="#{producte.nom}"
itemValue="#{producte}" converter="#{ProducteFitoConverter}"
forceSelection="true"
onkeyup="this.value = this.value.toUpperCase();">
<p:ajax event="itemSelect"
listener="#{trFitoBacking.handleSelect}"
update="text" global="false" />
<f:validator validatorId="qea.validators.EmptyFieldValidator" />
<f:attribute name="validationTitle" value=" NomComercial " />
</p:autoComplete>
</p:column>
<p:column>
<h:outputLabel>#{msgI18N.trFito}</h:outputLabel>
<h:outputText id="text"
value="#{traFitoBacking.resgistre}">
</h:outputText>
</p:column>
And this is my Backing Bean:
public void handleSelect(SelectEvent event) {
ProducteFitosanitari p=(ProducteFitosanitari)event.getObject();
setResgistre(Integer.toString(p.getNumRegistre()));
}
This works, but now I'm trying to update the outputText with id "text" with an empty String when the value of the autocomplete is empty.
How can I capture the event triggered when p:autoComplete is emptied?

Primefaces autoComplete generates 2 events: "change" and "itemSelect", for 2 methods of changing its content: typing or selecting from dropdown list. So you need to register 2 p:ajax listeners:
<p:autoComplete ... >
<p:ajax event="itemSelect" listener="#{bean.action}" process="#form"/>
<p:ajax event="change" listener="#{bean.action}" process="#form"/>
</p:autoComplete>
You'll need also 2nd server method signature:
public void action(AjaxBehaviorEvent event)
for capturing 'change' event.
Instead of event you can use onstart attribute with JavaScript to run... More options for p:ajax you'll find in Primefaces Users Guide, section "AjaxBehavior".

Related

How to attach an ajax event to a non-ClientBehaviorHolder component

In a form I have a p:inputText and a p:colorPickeras following :
<h:outputText value="#{messages.titre}" />
<p:inputText value="#{beanPlanningRessource.equipe.typeRessource.titre}">
</p:inputText>
<h:outputText value="#{messages.couleur}" />
<p:colorPicker value="#{beanPlanningRessource.equipe.typeRessource.couleur}">
</p:colorPicker>
And I have a p:commandButton which call a managedBean method as following :
<p:commandButton widgetVar="ajouter_equipe"
style="visibility: hidden;"
actionListener="#{beanPlanningRessource.ajouterEquipe()}" process="#this"
update=":#{p:component('dataTableEquipe')}, :#{p:component('formEquipe')}, :msgs" >
</p:commandButton>
The problem here is that the value in the p:inputText and p:colorPicker are always null in the managed bean, so in the p:inputText I added this line :
<p:ajax event="change" process="#this" />
and nowbeanPlanningRessource.equipe.typeRessource.titre is updated with the value in the p:inputText.
The problem I still have is that the p:colorPicker is a non-ClientBehaviorHolder component so I can't attach p:ajax to it and neither a f:ajax', so the value attached to thep:colorPicker:(beanPlanningRessource.equipe.typeRessource.couleur`) is always null.
How can I solve this?
Beside jquery you can also use the valueChangeListener
html:
<p:colorPicker valueChangeListener="#{beanPlanningRessource.colorChanged}" value="#{beanPlanningRessource.equipe.typeRessource.couleur}"/>
bean:
colorChanged(ValueChangeEvent event){
String newColor = event.getNewValue();
//do whatever you want with the new value
}

Bean listener does not get invoked when data table is sorted

I am displaying data in a JSF data table:
<p:dataTable value="#{mailServices.mailServices}" var="s">
<p:column headerText="ID" sortBy="#{s.ID}">
#{s.ID}
</p:column>
<p:column headerText="Name" sortBy="#{s.name}">
#{s.name}
</p:column>
<p:column headerText="Aktiv" sortBy="#{s.startup}">
<p:selectBooleanCheckbox value="#{s.startup}" >
<f:ajax event="change" listener="#{mailServices.toggleMailService}"/>
<f:attribute name="serviceid" value="#{s.ID}"/>
</p:selectBooleanCheckbox>
</p:column>
</p:dataTable>
As long as i do not click on the column headers the listener gets invoked when clicking a checkbox. But as soon as I have sorted a column (no matter what column it is) the listener does not get invoked.
My listener looks like:
public void toggleMailService(AjaxBehaviorEvent e) {
//code
}
Could it be that I am using the <f:ajax event...> wrongly?
Thanks in advance!
What #BalusC said, tag is missing a left bracket:
<f:ajax event="change" listener="#MailServices.toggleMailService}"/>
Try with
<f:ajax event="change" listener="#{MailServices.toggleMailService}"/>
Also asure that your Bean is being declared as "MailServices"
#ManagedBean(name="MailServices")

How to update a specific cell on a PrimeFaces dataTable

In my dataTable I am linking each article with a specific task.
On the click of a commandButton a list of tasks shows up, so I want on the select of a task, update a specific cell in the dataTable (outputText with id="columnTache") without updating the rest of my dataTable.
<p:dataTable value="#{myController.articleList}"
id="tabArticle"
var="article"
rowKey="#{article.id}" >
<p:column headerText="quantite" >
<pe:inputNumber value="#{article.quantite}" />
</p:column>
<p:column headerText="taches" >
<h:outputText value="#{article.tache.libelleTache}" id="columnTache" />
</p:column>
<p:column headerText="taches" >
<p:commandButton oncomplete="PF('dialogTasks').show();" update=":formSelectAffecterTache">
<p:ajax event="click" listener="#{myController.setArticle(article)}" />
</p:commandButton>
</p:column>
</p:dataTable>
<p:dialog header="#{bundleTech.lbl_taches}" widgetVar="dialogTasks" >
<h:panelGrid columns="1" >
<h:form id="formSelectAffecterTache">
<ui:include src="/pages/listTacheSelect.xhtml">
<ui:param name="bean" value="#{myController}" />
<ui:param name="action" value="affecterTache" />
</ui:include>
</h:form>
</h:panelGrid>
</p:dialog>
The update of my dataTable is in the managed bean:
public void affecterTache() {
article.setTache(selectedSingleTache);
RequestContext.getCurrentInstance().update("form:tabArticle");
}
A dataTable is a naming container, so components within it will be prepended with the dataTable's id. Also, each iteration of data presented in the table (each row) will have effect of the generated ids. Since a form is also a naming container, your outputText component ids will be generated as formId:tabArticle:0:columnTache in the first row, formId:tabArticle:0:columnTache in the second row, etc.
If you would set an id on your commandButton you will get formId:tabArticle:0:myButton, formId:tabArticle:1:myButton etc. You can use this id in your click handler to create the corresponding inputText clientId. But, since you pass article to a method, you are not able to check which button was clicked. So first of all change the click listeners method to:
public void useArticle(AjaxBehaviorEvent event) {
UIComponent component = event.getComponent();
}
Now, you know which button was clicked (event.getComponent()), but you need your article as well. You can set that as an attribute to your button in XHTML:
<p:commandButton id="myButton"
oncomplete="PF('dialogTasks').show();"
update=":formSelectAffecterTache">
<p:ajax event="click"
listener="#{myController.useArticle}" />
<f:attribute name="article"
value="#{article}" />
</p:commandButton>
This attribute can be read in your listener:
Article article = (Article) component.getAttributes().get("article");
Now, for updating the inputText, simply use the button's clientId:
String update = component.getClientId().replace(":myButton", ":columnTache");
Store it in your bean, and when you are ready to do so, update:
RequestContext.getCurrentInstance().update(update);
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
Send additional parameter to Ajax event listener

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

PrimeFaces PickList component, how to get all target values to one InputText component?

I created xhtml page with one inputText and one commandButton component. When I clicked on button is displaying overlayPanel with pickList and one commandButton under list. I want to get all target values and put it into inputText (this component must be only one). Can you help me how to do it?
Below is xhtml code that I wrote for now:
<h:panelGrid id="displayPlayers" columns="3">
<ui:repeat value="#{pickListBean.players.target}" var="player">
<p:inputText id="input2" value="#{player.name}" />
</ui:repeat>
<p:commandButton id="overPanBtn2" value="overPanBtn2" type="button" />
</h:panelGrid>
<p:overlayPanel id="chartPanel2" for="overPanBtn2" hideEffect="fade">
<p:pickList id="pickList4" value="#{pickListBean.players}" var="player" itemLabel="#{player}" itemValue="#{player}" converter="playerConverter">
<p:column style="width:75%;">
#{player.name}
</p:column>
<p:column style="width:75%;">
#{player.number}
</p:column>
</p:pickList>
<p:commandButton id="playerSubmit4" value="Ok" update="displayPlayers" style="margin-top:5px" />
</p:overlayPanel>
I will be grateful for help.
In your case it should be something like that, you only have to follow the showcase example:
XHTML
<p:pickList id="pickList4" value="#{pickListBean.players}" var="player" itemLabel="#{player}" itemValue="#{player}" converter="playerConverter">
<p:ajax event="transfer" listener="#{pickListBean.onTransfer}" update="msg" />
<p:column style="width:75%;">
#{player.name}
</p:column>
<p:column style="width:75%;">
#{player.number}
</p:column>
</p:pickList>
BACKING BEAN
String selectedPlayerNames;
//GETTER
public void onTransfer(TransferEvent event) {
selectedPlayerNames = "";
for (Player p : players.getTarget()){
selectedPlayerNames += p.getName() + " ";
}
}
Just call the event when transfer happens, and save the targeted values into the String. Then bind this String property to a p:inputText.

Resources