One of the most common approaches to change locale in JSF+Seam - with <h:selectOneMenu>:
<h:form action="#{localeSelector.select}" rendered="false">
<h:selectOneMenu value="#{localeSelector.language}" onchange="submit()">
<f:selectItem itemLabel="English" itemValue="en" />
<f:selectItem itemLabel="Francais" itemValue="fr" />
</h:selectOneMenu>
</h:form>
I want to implement locale changes with buttons. So, the question is - how to pass the parameter (en, fr, etc.) to update the bean with <h:commandButton>? Maybe <h:inputHidden> would help?
Either pass as method argument (only if your environment supports EL 2.2),
<h:commandButton value="English" action="#{localeSelector.change('en')}" />
<h:commandButton value="Deutsch" action="#{localeSelector.change('de')}" />
<h:commandButton value="Français" action="#{localeSelector.change('fr')}" />
with
public void change(String language) {
locale = new Locale(language);
// ...
}
Or use <f:setPropertyActionListener>
<h:commandButton value="English" action="#{localeSelector.change}">
<f:setPropertyActionListener target="#{localeSelector.language}" value="en" />
</h:commandButton>
<h:commandButton value="Deutsch" action="#{localeSelector.change}">
<f:setPropertyActionListener target="#{localeSelector.language}" value="de" />
</h:commandButton>
<h:commandButton value="Français" action="#{localeSelector.change}">
<f:setPropertyActionListener target="#{localeSelector.language}" value="fr" />
</h:commandButton>
with
private String language;
public void change() {
locale = new Locale(language);
// ...
}
Or use <f:param>
<h:commandButton value="English" action="#{localeSelector.change}">
<f:param name="language" value="en" />
</h:commandButton>
<h:commandButton value="Deutsch" action="#{localeSelector.change}">
<f:param name="language" value="de" />
</h:commandButton>
<h:commandButton value="Français" action="#{localeSelector.change}">
<f:param name="language" value="fr" />
</h:commandButton>
with
public void change() {
locale = new Locale(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("language"));
// ...
}
(you can also let JSF automatically set it by a #ManagedProperty("#{param.language}"), but this requires the bean to be request scoped, or a <f:viewParam>, see also ViewParam vs #ManagedProperty(value = "#{param.id}"))
Enough ways to pass a parameter from view to controller. Take your pick. The <h:inputHidden> serves in JSF context a somewhat different purpose and it can only be manipulated by JavaScript in the onclick which is ugly.
Related
This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 5 years ago.
I have a jsf page where I have this form :
<h:commandButton id="submit" value="Submit">
<h:inputText id="locationInputId" value="#{historicCtrl.historic.search}" ></h:inputText>
<f:ajax event="click" render="resultGroup" listener="#{cSVobjectCtrl.doRender}"/>
<label for="lat">Latitude</label>
<h:inputText id="lat" value="#{cSVobjectCtrl.lat}"/>
<label for ="lng">Longitude</label>
<h:inputText id="lng" value="#{cSVobjectCtrl.lng}"/>
<f:actionListener binding="#{historicCtrl.insertSearch(2)}"/>
</h:commandButton >
The problem is that the line :
< f:actionListener binding="#{historicCtrl.insertSearch(2)}"/>
Is ignored and I don't know why.
I tried a easier version of the code :
<h:form>
<h:outputText value="Lieu"/>
<h:inputText id="login" value="#{historicCtrl.historic.search}" required="true"></h:inputText>
<br/>
<h:commandButton value="Search">
<h:outputText id ="textToInsertId" value="#{historicCtrl.insertSearch(2)}"/>
</h:commandButton>
</h:form>
This one is working, I can see the trace that the method is supposed to print on the console and I have the insertion in my database.
On the opposite the first code that I wrote in the message isn't working as expected. Indeed, all is working naturally except the f;actionListener as I explain above.
Why is this instruction ingnored ?
Your code is really confusing, but I'll concentrate on the question and provide an example of how your code should propably look like.
If you want to bind an actionListener you have to bind it to an object that implements ActionListener-Interface and not to a method, for example:
facelet
<f:actionListener binding="#{historicCtrl}" />
ActionListener
#ManagedBean
#ViewScoped
public class HistoricCtrl implements Serializable, ActionListener {
private static final long serialVersionUID = 6307961450435094233L;
#Override
public void processAction(ActionEvent e) throws AbortProcessingException {
// TODO implement
}
}
If you use binding you can't pass an argument to your actionListener. The better approach is to use actionListener attribute of h:commandButton. In this case your code should look like this:
<h:form id="form">
<h:inputText id="locationInputId" value="#{historicCtrl.historic.search}" />
<br />
<h:outputLabel for="lat" value="Latitude" />
<h:inputText id="lat" value="#{cSVobjectCtrl.lat}"/>
<br />
<h:outputLabel for="lng" value="Longitude" />
<h:inputText id="lng" value="#{cSVobjectCtrl.lng}"/>
<br />
<h:commandButton id="submit" value="Submit" actionListener="#{historicCtrl.insertSearch(2)}">
<f:ajax execute="form" render="resultGroup" listener="#{cSVobjectCtrl.doRender}"/>
</h:commandButton>
</h:form>
I'm facing problem with passing object to backing bean from actionListener in commandLink. What I have, is a bean MeasureBean and a xhtml file, that uses the bean.
In the xhtml I have:
<p:selectOneListbox var="ch">
<f:selectItems value="#{MeasureBean.checkpoints}" var="cp" itemValue="#{cp}" />
<p:column>
<h:outputText value="#{ch.name}" />
</p:column>
<p:column>
<h:commandLink actionListener="#{MeasureBean.onCheckpointRemoved(ch)}">
<h:graphicImage library="#{ctx.theme}" name="images/delete.gif" />
<f:ajax event="click" />
</h:commandLink>
</p:column>
</p:selectOneListbox>
In the bean I have method:
public void onCheckpointRemoved(Checkpoint viewCheckpoint) {
System.out.println(viewCheckpoint);
// TODO
}
The problem is, that regardless of whethert I use the tag <f:ajax> or not, the parameter viewCheckpoint of the method in bean is always null. I need to pass that parameter to the bean. It doesn't have to be the whole object, it is allowed to pass just the id of the checkpoint. What I also tried, was:
<h:commandLink actionListener="#{MeasureBean.onCheckpointRemoved(cp)}">
(cp instead of ch). But no difference.
Please help,
Mateusz
You forgot to set the value of <p:selectOneListBox>. Also, you'll have to create a converter.
You can check an example of converter in PrimeFaces Showcase
<p:selectOneListbox var="ch" value="#{MeasureBean.checkPointTest}" converter="checkPointConverter">
<f:selectItems value="#{MeasureBean.checkpoints}" var="cp" itemValue="#{cp}" />
<p:column>
<h:outputText value="#{ch.name}" />
</p:column>
<p:column>
<h:commandLink actionListener="#{MeasureBean.onCheckpointRemoved(ch)}">
<h:graphicImage library="#{ctx.theme}" name="images/delete.gif" />
<f:ajax event="click" />
</h:commandLink>
</p:column>
</p:selectOneListbox>
Checkpoint checkPointTest;
// getter/setter....
public void onCheckpointRemoved(Checkpoint viewCheckpoint) {
System.out.println(viewCheckpoint);
// TODO
}
I have a selectOneMenu and a InputText. I want to change readOnly="false" property of InputText when I select other option of selectOneMenu.
These are codes
<h:form>
<h:selectOneMenu id="customerCombo"
value="#{customer.selectedBank}"
required="true"
requiredMessage="Please select one">
<f:selectItem itemLabel="Seçiniz" noSelectionOption="true" />
<f:selectItems value="#{customer.banks}" />
<f:selectItem itemValue="Other" itemLabel="Other"/>
<f:validateRequired/>
</h:selectOneMenu>
<h:message for="customerCombo"/>
<br /><br />
<h:outputText value="other text" />
<h:inputText id="digerText" readonly="true"/>
<br /><br />
<h:commandButton value="submit" action="customerResult" />
</h:form>
Define a variable in your #ViewScoped backing bean that will correspond to the readOnly state
private boolean readOnly;
//getter and setter
Define a method that will toggle the state of the readOnly variable. This method will be called via ajax
public void toggleReadOnly(){
if(selectedBank.equals("Other"){
readOnly = true;
}
}
Bind the value of the readOnly variable to the <h:inputText/>
<h:inputText id="digerText" readonly="#{bean.readOnly}"/>
bean being (hehe) the name of your backing bean
Trigger the toggleReadOnly method from your dropdown menu
<h:selectOneMenu id="customerCombo"
value="#{customer.selectedBank}"
required="true"
requiredMessage="Please select one">
<f:ajax listener="#{bean.toggleReadOnly}" render="digerText"/>
</h:selectOneMenu>
What I want to do is implement a JSF page that will return to the prior page once it is done. This is with #RequestScoped beans.
The original page called viewDocument.xhtml has this:
<f:metadata>
<f:viewParam name="ID" value="#{viewDocument.id}" />
</f:metadata>
(bunch of stuff)
<h:link outcome="editThingy" value="Edit Thingy">
<f:param name="ID" value="#{viewDocument.doc.id}" />
<f:param name="Return" value="viewDocument" />
</h:link>
The target page editThingy.xhtml has its own backing bean, and looks like this:
<f:metadata>
<f:viewParam name="ID" value="#{editThingy.id}" />
<f:viewParam name="Return" value="#{editThingy.navReturn}" />
</f:metadata>
<h:form>
(bunch of stuff)
<p:commandButton value="Save" action="#{editThingy.save}" >
<f:param name="ID" value="#{editThingy.id}" />
</p:commandButton>
<p:commandButton value="Cancel" action="#{editThingy.navReturn}" >
<f:param name="ID" value="#{editThingy.id}" />
</p:commandButton>
</h:form>
The idea is that both buttons (cancel or save) would return to the page indicated by the Return request parameter, with the new page getting the ID request parameter so it pulls up the same record that EditThingy worked on.
BZZZT! The p:commandButton does a POST and not a GET, so it can't use f:param. However if I try to use p:button there is no attribute to call the backing bean!
Is there any way to implement what I want?
The <f:param> should work just fine. You only need to retain the Return parameter for subsequent requests as well, exactly as you did for the ID parameter, otherwise it's lost during processing the form submit because your bean is request scoped instead of view scoped.
Thus so,
<p:commandButton value="Save" action="#{editThingy.save}" >
<f:param name="ID" value="#{editThingy.id}" />
<f:param name="Return" value="#{editThingy.navReturn} " />
</p:commandButton>
<p:commandButton value="Cancel" action="#{editThingy.cancel}" >
<f:param name="ID" value="#{editThingy.id}" />
<f:param name="Return" value="#{editThingy.navReturn} " />
</p:commandButton>
with
public String save() {
// ...
return navReturn;
}
public String cancel() {
return navReturn;
}
Update: based on the comments, the functional requirement has now become more clear. The cancel button can also be done as follows, assuming that you don't need to invoke a backing bean action method at all on cancel:
<p:button value="Cancel" outcome="#{editThingy.navReturn}" >
<f:param name="ID" value="#{editThingy.id}" />
</p:button>
The save button can return the following:
return navReturn + "?id=" + id + "&faces-redirect=true";
<h:outputLink value="#{beanname.path}">
<h:outputText value="Output label"></h:outputText>
<f:param name name="name" value="tommy"/>
</h:outputLink>
http://127.0.0.1:7101/projectt/faces/index.jsp?name=tommy
my URL appears with the param value. I want to hide it in the URL and get it in the bean class.
So, you want a POST request? Use <h:commandLink> instead.
<h:form>
<h:commandLink value="Output label" action="#{beanname.outcome}">
<f:param name name="name" value="tommy"/>
</h:commandLink>
</h:form>
The parameter can be set as
#ManagedProperty("#{param.name}")
private String name;
or can passed by <f:setPropertyActionListener> instead:
<h:form>
<h:commandLink value="Output label" action="#{beanname.outcome}">
<f:setPropertyActionListener target="#{beanname.name}" value="tommy"/>
</h:commandLink>
</h:form>
or when you're already on a Servlet 3.0 / EL 2.2 capable container (Tomcat 7, Glassfish 3, etc), just pass it as action method argument:
<h:form>
<h:commandLink value="Output label" action="#{beanname.outcome('tommy')}" />
</h:form>
with
public String outcome(String name) {
// ...
return "index";
}