JSF ActionListener Event - jsf-2

I am using an ActionListener to find out if a next button was pressed, I plan to have a previous button implemented later.
This is the xhtml
<h:commandLink styleClass="btn btn-info" id="tablePagerNext"
value="Next" actionListener="#{records.increnemt}">
<f:ajax render="dataTableRecords" />
</h:commandLink>
Now that is supposed to call my method here:
public void increnemt(ActionEvent e){
System.out.println("The action taken was " + e.getComponent().getAttributes().get("action"));
}
Where based on the action it will call an appropriate method (This just prints out The action taken was null). I know that in swing you can do
if(e.getSource == jButton){
//do this
}else{}
in JSF there is a .getSource() what I am not sure of is what that source is based on the xhtml above. I am not really sure what I am looking for when the event fires.
Could someone clear this up for me?

As per my understanding you wanted to know which button was clicked (next or prev or whatever)
As per ActionEvent documentation you dont have any method to identify button uniquely. I wish you will research on f:param to set some value to cross check the same in controller bean method (increnemt).

Related

JSF 2 + Primefaces: Need to update bean property on menu click before rendering dialog

I have a p:menuitem that needs to (1) update a backing bean property when clicked, and then (2) show a p:dialog.
This is the set up I have:
<p:menuitem value="Show Dialog"
oncomplete="dialog_widget.show();"
update=":dialog"
actionListener="#{bean.setCurrentAction}">
</p:menuitem>
<p:dialog widgetVar="dialog_widget" id="dialog" dynamic="true">
<h:form>
<p:inputText value="#{bean.record.text} />
// the proper rendering of this dialog form depends on bean.currentAction
// being set during JSF Phase 4 Update Model Values
</p:dialog>
And the backing bean:
public R getRecord() {
if (currentAction == null) {
return null;
}
return currentAction == NEW ? newRecord : selectedRecord;
}
The problem is that actionListeners and actions are only executed during Phase 5 and I need the bean.currentAction to be set before that so the dialog can be properly updated and rendered.
** A little background on what I'm trying to achieve: the dialog form is used to Create new records as well as Update exsiting records (Add and Edit Dialog). So the "currentAction" on the bean indicates which action the user is doing. Depending on which action, the form needs to use different model objects ("newRecord" or "selectedRecord") to pull and save the form data to.
Although not a very elegant solution you can use PrimeFaces' RequestContext's update method to set update target and use the execute method to show your dialog in your actionListener after setting the needed property.
If you requirement is to call the backing bean method before the dialog opens then you can go for a ajax function (i don't know whether you are allowed to use ajax in your application). for p:menuItem there is a function called onclick, where you can call a a4j:ajax function through which you can call a backing bean method and update the model before dialog opens.
By default action is called during "Invoke Application" phase. You can add immediate="true" attribute in p:menuitem tag. This will call action in "Apply Request Values" phase.

Composite Component and setPropertyActionListener

I have a composite component that have a dialog...
Inside the dialog I have the following piece of code:
<p:commandButton id="selectButton" icon="ui-icon-check" oncomplete="lookupDialog.hide();" update=":#{cc.clientId}:#{cc.attrs.fieldId}_panelGrid">
<f:setPropertyActionListener target="#{cc.attrs.targetValue}" value="#{entity}" />
</p:commandButton>
So, when the button is clicked, the dialog vanishes, but the property isn´t set.
There is no errors, no warnings, nothing! So I simply don´t know what is happening...
If you need anymore details, please just say so! :)
***EDIT
This is a related question, but not really what I want to do...
Pass Argument to a composite-component action attribute
I just need the propertyActionListener to work.
Here some extra information:
<cc:attribute name="targetValue" required="true"/>
the value:
targetValue="#{acaoController.entity.responsavel}"
Where inside the bean (acaoController)
I have an entity...
And inside the entity I have another object, that is "responsavel".
Try checking setters and getters of responsavel getting called when you close the dialog box.
Otherwise you can use Flash to pass on the value between components. In the action method of command button,
Flash flash = FaceUtil.getFacesContext().getExternalContext().getFlash();
flash.put("entity",entity);
And you can extract the value like this:
Flash flash = FaceUtil.getFacesContext().getExternalContext().getFlash();
responsavel = (Responsavel) flash.get("entity");

<h:commandButton> does not invoke action

During some tests made using JSF 2 (mojarra on Glassfish 3.1.1) I've faced with strange behavior I can't explain.
This is my managed bean:
#ManagedBean
#RequestScoped
public class TestBean {
private int id;
public void hideButton() {
id = 0;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Here is my xhtml page
<h:form>
<h:inputHidden value="#{testBean.id}"/>
<h:outputText value="#{testBean.id}"/>
<h:commandButton value="set 1"
actionListener="#{testBean.setId(1)}">
</h:commandButton>
<h:commandButton value="hide button"
action="#{testBean.hideButton}" rendered="#{testBean.id > 0}">
</h:commandButton>
</h:form>
I expected, the button "hide button" is not visible on initial load of the page and this is really the fact. After a click on the button "set 1", the button "hide button" appeares and that is also to expect.
Really not understandable thing to me is the fact the subsequent click on the button "hide button" does not invoke the method testBean.hideButton and set the id to 0.
I've read the very useful answer from BalusC (thanks a lot really) here
commandButton/commandLink/ajax action/listener method not invoked or input value not updated
and recognize, the problem is related to the attribute "rendered", if I remove it, the action is invoked.
But as far as I aware, the class member must be initialized during the UPDATE MODEL VALUES phase and the condition mentioned in the attribute rendered should be evaluated to true during INVOKE APPLICATION phase and the action should be invoked.
The example works if I change the scope of the bean to View/Session.
But it also works fine if I remove the render attribute from the "hide button"
Would somebody explain such behavior?
In other words, at what phase the expression of the rendered attribute is evaluated to make decision not to invoke the action?
The rendered attribute is also evaluated during apply request values phase, at the moment when JSF needs to identify which action needs to be invoked. If it evaluates false, then the action can't be identified and will thus also not be invoked.
The problem is caused by the too narrow managed bean scope. As your managed bean is request scoped, it get trashed by end of response and recreated (with all properties set to default) on any subsequent request. The model value on which the rendered attribute depends will only be updated during update model values phase, which is too late. You should be placing the managed bean in view scope instead.
Apart from changing the bean scope to view scope, another way is to check the request parameter map value instead in the rendered attribute.
<h:form id="form">
<h:inputHidden id="id" ... />
<h:commandButton ... rendered="#{param['form:id'] gt 0}" />
</h:form>
(by the way your usage of > instead of gt indicates that you're using the deprecated JSP view technology instead of Facelets, I would strongly recommend to migrate to Facelets)
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated
How to choose the right bean scope?
I've found myself the reason of the problem.
The method UIComponentBase.processDecodes (at the Apply Request Values phase) calls isRendered, which returns false, because it is before the Update Model Values. Which skips the decode of the component.
There are some workarounds possible, all of them imho are not cool, but nevertheless it works
It is possible manually to set necessary value in managed bean in (post)constructor from request parameters.
Or to use

f:param not working when used with trinidad 2

I am using JSF 2 Trinidad 2(MyFaces) and trying to use f:param in a command button
<tr:commandButton text="Submit" action={backingBean.actionSubmit}>
<f:param name="isSubmit" value="Yes" />
</tr:commandButton>
Basically I am trying to pass the param value for submit button and only perform the validation if a Submit button is clicked adding the condition to the required attribute for input elements to check for the submit button.
Is there a way to identify a particular button click in JSF2/Trinidad2 so that I can check for that button click in the validation method.
I am using JSF 1.2 but I think it works in JSF 2.0 the same way.
For your commandButton use an actionListener instead of action.
<tr:commandButton text="Submit" actionListener={backingBean.actionSubmit}>
Within your bean you can get the id of your button:
public void actionSubmit(ActionEvent event)
{
event.getComponent().getId();
}
You could consider to use <tr:setActionListener/>. In your case you could use something like:
<tr:commandButton text="Submit" action="#{backingBean.actionSubmit}">
<tr:setActionListener from="submit" to="#{backingBean.pressedButton}" />
</tr:commandButton>
Basically you use it to copy an object from the from attribute to the to attribute. Note that you could use EL in the from attribute as well (#{someBean.someObject}).
In you backing bean you need to add a String member called pressedButton (with getter and setter). Now you can use the following code in your actionSubmit
if ("submit".equals(pressedButton))
{
System.out.println("You pressed 'sumbit'");
}

JSF immediate="true" for cancel button doesn't work

I have a two tab page, one tab is the record list, click on the record will switch to the Edit tab, and there's Save and Cancel buttons in the Edit tab.
Now, I click on the record #1, do some edit, and click the Cancel button. Certainly I don't want to validate the form because it's canceled, so I set immediate="true" on the Cancel button. Now the edit tab is closed, back to the record list. Then, I click on another record #2, the problem occurred: In the edit tab, it's still the previous content of record #1, rather then record #2. I've checked the variables in debug view, the back bean for the edit form was ACTUALLY filled with record #2.
I.e., something broken after an immediate command.
(Everything had been well before I have added the validation and immediate="true".)
class FormBean {
Record activeRecord;
...
public void clickOnList() {
activeRecord = loadRecord(clickIndex);
}
public void cancelForm() {
activeRecord = null;
}
}
page.xhtml:
<h:form id="main">
...
<p:tab title="Edit" rendered="#{formBean.activeRecord != null}">
...
<p:commandButton value="Cancel"
actionListener="#{formBean.cancelForm}"
update="main" async="true" immediate="true" />
</p:tab>
</h:form>
The immediate="true" doesn't work nicely with ajax requests on the same view. It boils down to that the submitted-but-not-validated values are still there in the input components. Without ajax, a normal synchronous request/response of a subsequent form submit would silently "solve" this. But with ajax, this does not happen. The submitted values of the previous ajax request are still there in the input components. When UIInput#getSubmittedValue() doesn't return null, it will be displayed instead, irrespective of the (changed) model value.
Basically, when you want to stick to ajax for a cancel button, you need to exclude the inputs from being processed instead of relying on the immediate="true" (which is actually kind of a hack). In standard JSF <f:ajax> terms, you could do this with execute="#this" (which is actually the default) on the button instead of execute="#form". The PrimeFaces buttons defaults to #form, so you need to change this:
<p:commandButton value="Cancel"
actionListener="#{formBean.cancelForm}"
update="main" async="true" process="#this" />

Resources