My actionListener is ignored [duplicate] - jsf

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>

Related

JSF setters not get invoked [duplicate]

This question already has answers here:
Why my jsf <h:inputText> dont set the value in bean class?
(2 answers)
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 4 years ago.
I have no idea why my setters are not invoked while processing form. I see in network browser tool, that POST request is fired with correct (updated) data. But it doesn't affects my binded bean.
<p:commandButton value="Action"
immediate="true"
action="#{beanView.actionForString('5/13/015')}"
oncomplete="PF('some_widget').show()"
update="some_widget_update"/>
<p:dialog id="some_widget_update" widgetVar="some_widget" width="800">
<ui:include src="/view.xhtml" />
</p:dialog>
Template form:
<h:form id="contentForm"
prependId="false"
enctype="multipart/form-data">
<p:messages autoUpdate="true"
globalOnly="true"
showDetail="true"
for="formMessages"
closable="true" />
<div id="starterDiv"
class="ui-fluid">
<ui:insert name="formAsd" />
</div>
</h:form>
And view.xhtml:
<ui:define name="formAsd">
<h:panelGroup rendered="#{beanView.payment!= null}">
<c:set var="payment" value="#{beanView.payment}" />
<div class="ui-g with_background">
<div class="ui-g-2">Payment Id:</div>
<div class="ui-g-2">
<p:inputText value="#{payment.id}"/>
</div>
</div>
<p:commandButton value="Save"
immediate="true"
process="contentForm"
action="#{beanView.save()}" style="width: 150px"/>
</h:panelGroup>
</ui:define>
The bean view looks like that:
#ManagedBean
#ViewScoped
#Data
#FieldDefaults(level = AccessLevel.PRIVATE)
public class BeanView implements Serializable {
Payment payment;
#Setter(onMethod=#__({#Autowired}))
transient PaymentService paymentService;
public void save() {
paymentService.registerPayment(payment); // here It's unchanged!!
}
public void actionForString(String asd) {
payment= paymentService.takeForString(asd)
}
}
Getter works fine, I can see values which service returns in my view.xhtml. Then as I said above, after changing the input value and clicking save button, my debugger shows old value (from intialization in actionFroString) method. Why it is happening?
I believe your problem is immediate="true" on your Command Button. That command immediate="true" tells JSF to skip the validation and binding phase which is why your setters are not being called. This detailed explanation explains why: https://dzone.com/articles/jsf-and-immediate-attribute

Bean Validation does not work for model properties which are not tied to view

I figured out, that my bean validation does not work for model properties which are not tied to view.
Model:
#NotNull
private String name;
public String submit() {
...
}
View:
<h:form>
<h:inputText type="*" value="#{myBean.name}" />
<h:commandButton type="submit" value="name" action="#{myBean.submit}" />
</h:form>
So if someone tries to call the function without the parameter "name" the bean is not validating the attribute und calls the method "submit".
<h:form>
<h:commandButton type="submit" value="Name" action="#{myBean.submit}" />
</h:form>
So the question is how can I protect my bean, that the code in submit is not executed if someone tamper the XHMTML and does not transfer "name".
Maybe someone can help me :)

How to pass a parameter along with h:commandButton

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.

Passing inputtext value as parameter

I want to pass user input to another page as a parameter. Here is my code:
<h:form>
<h:inputText value="#{indexBean.word}"/>
<h:commandLink value="Ara" action="word.xhtml">
<f:param value="#{indexBean.word}" name="word"/>
</h:commandLink>
</h:form>
Well, this is not working. I can read the inputtext value in my backing bean but I can't send it to word.xhtml.
Here is another approach I tried:
<h:form>
<h:inputText binding="#{indexBean.textInput}"/>
<h:commandLink value="Ara" action="word.xhtml">
<f:param value="#{indexBean.textInput.value}" name="word"/>
</h:commandLink>
</h:form>
This is also not working.
So, what am I doing wrong?
Your concrete problem is caused because the <f:param> is evaluated when the page with the form is requested, not when the form is submitted. So it remains the same value as on the initial request.
The concrete functional requirement is not exactly clear, but the particular functional requirement can be solved in basically two ways:
Use plain HTML.
<form action="word.xhtml">
<input type="text" name="word" />
<input type="submit" value="Ara" />
</form>
Send a redirect in action method.
<h:form>
<h:inputText value="#{bean.word}" />
<h:commandButton value="Ara" action="#{bean.ara}" />
</h:form>
with
public String ara() {
return "word.xhtml?faces-redirect=true&word=" + URLEncoder.encode(word, "UTF-8");
}

Glassfish complaining about JSF component IDs

I am very new to JSF (v2.0) and I am attempting to learn it at places like netbeans.org and coreservlets.com. I am working on a very simple "add/subtract/multiply/divide" Java webapp and I have run into a problem. When I first started out, the application was enter two numbers and hit a '+' key and they would be automatically added together. Now that I have added more complexity I am having trouble getting the operation to the managed bean. This is what I had when it was just "add":
<h:inputText styleClass="display" id="number01" size="4" maxlength="3" value="#{Calculator.number01}" />
<h:inputText styleClass="display" id="number02" size="4" maxlength="3" value="#{Calculator.number02}" />
<h:commandButton id="add" action="answer" value="+" />
For the "answer" page, I display the answer like this:
<h:outputText value="#{Calculator.answer}" />
I had the proper getters and setters in the Calculator.java managed bean and the operation worked perfectly.
Now I have added the other three operations and I am having trouble visualizing how to get the operation parameter to the bean so that I can switch around it. I tried this:
<h:commandButton id="operation" action="answer" value="+" />
<h:commandButton id="operation" action="answer" value="-" />
<h:commandButton id="operation" action="answer" value="*" />
<h:commandButton id="operation" action="answer" value="/" />
However, Glassfish complained that I have already used "operation" once and I am trying to use it four times here.
Any adivce/tips on how to get multiple operations to the managed bean so that it can preform the desired operation?
Thank you for taking the time to read.
The component id should indeed be unique. This is implicitly required by the HTML specification. You know, all JSF does is just generating the appropriate HTML/CSS/JS code. Give them all a different id or just leave it away, it has no additional value in this specific situation (unless you'd like to hook some CSS/JS on it).
To achieve your functional requirement, you may find f:setPropertyActionListener useful.
<h:commandButton action="answer" value="+">
<f:setPropertyActionListener target="#{calculator.operation}" value="+" />
</h:commandButton>
<h:commandButton action="answer" value="-">
<f:setPropertyActionListener target="#{calculator.operation}" value="-" />
</h:commandButton>
<h:commandButton action="answer" value="*">
<f:setPropertyActionListener target="#{calculator.operation}" value="*" />
</h:commandButton>
<h:commandButton action="answer" value="/">
<f:setPropertyActionListener target="#{calculator.operation}" value="/" />
</h:commandButton>
And have a property operation in your calculator managed bean:
private String operation; // +setter.
You can access it in the getAnswer() method and handle accordingly.
Alternatively, let the buttons each point to a different bean action but which returns all "answer":
<h:commandButton action="#{calculator.add}" value="+" />
<h:commandButton action="#{calculator.substract}" value="-" />
<h:commandButton action="#{calculator.multiply}" value="*" />
<h:commandButton action="#{calculator.divide}" value="/" />
with the following methods in your calculator managed bean:
public String add() {
answer = number1 + number2;
return "answer";
}
public String substract() {
answer = number1 - number2;
return "answer";
}
// etc...
and just let getAnswer() return answer and do nothing else there. That's a more clean separation of responsibilities.

Resources