How to check which primefaces ajax event triggered into java method - jsf

let's say we have two types of events that will be directed to the same method as mentioned in the below example
<p:ajax event="cellEdit" listener="#{bean.eventype}"/>
<p:ajax event="change" listener="#{bean.eventype}"/>
and here is the bean method for example
public void eventype(){
println("");
}
The question is, is it possible if I want to identify which value came from which events in eventype method?
Is it possible to differentiate both mentioned events in eventype method?
Edited:
I did try to add eventype(AjaxBehaviorEvent event) and use event.getSource() but it seems like am just getting the source details like org.inputtext.component#something.

The type of event is posted in the request in order for the component being able to decode it to trigger the correct event. The parameter name is javax.faces.behavior.event, which you can get like:
String eventType = FacesContext.getCurrentInstance()
.getExternalContext()
.getRequestParameterMap()
.get("javax.faces.behavior.event");
This is implemented in PrimeFaces like:
https://github.com/primefaces/primefaces/blob/042b5a14116cd4a279a114883a8575e0788494b8/primefaces/src/main/java/org/primefaces/util/ComponentUtils.java#L197-L224
Note that you can also use the PrimeFaces constant Constants.RequestParams.PARTIAL_BEHAVIOR_EVENT_PARAM in your code instead of hardcoding "javax.faces.behavior.event".

Related

Primefaces Picklist trigger transfer event only on add

I have a picklist component (Primefaces 6.x ) in one of my pages. The picklist has a "transfer" event listener as shown in the showcase:
<p:ajax event="transfer" listener="#{pickListView.onTransfer}" update="msg" />
This works pretty well and my method is called every time i add or remove items from the target list.
My question is if it is possible to trigger the event handler only when adding items in the target list or if there is a way to catch the remove from target action in my method and ignore all validations that i am doing in bean method.
There is an advantage to source being open and having a good IDE for code completion. Both can show that the TransferEvent.java has isAdd() and isRemove() methods. These can easily be used to differentiate in an eventHandler which one is actually used.
public void onTransfer(TransferEvent event) {
if (event.isAdd()) {
// Do actual work
}
}

how to update a component on p:terminal command?

p:terminal does not have a update attribute.
Does it support any kind of ajax event?
how do I update another jsf component as a response to a terminal command?
It does not have any ajax events as can be seen in the documentation and/or the source. But in the implementation of commands for the terminal that you implement yourself, you can do anything you want. Including using the RequestContext to update other components.
At least that is what I expected (and did not explicitly test, sorry). Updating from the commandHandler does not work since the commandHandler is called during the render response phase and you cannot add updates to components in that phase.
See also the comment on the answer here: Can I update a JSF component from a JSF backing bean method?.
So the actual good answer is the one from the #Leo himself (although this answer helped a little ;-))
Here what worked for me
<p:terminal
id="terminal"
widgetVar="term"
prompt="Lab >> "
commandHandler="#{labMB.handleCommand}"
welcomeMessage="Welcome to Lab" />
<p:remoteCommand
name="rc"
update="history" />
<p:dataTable
id="history"(...)
and
public String handleCommand(String command, String[] params) {
RequestContext context = RequestContext.getCurrentInstance();
//(do things here)
context.execute("rc();");
}
it seems that just calling
context.update("form:history");

Can JSF be configured to not invoke Entity setter unless the field actually changed?

When a JSF form field is wired into an entity bean field (which is mapped to a DB field), each setter in the entity bean is called regardless of whether the user changed the form field value in the front end, i.e. the setters on unchanged fields are invoked the same as those that have changed but their new value is the same as the old value.
My question is simple: Is there a way to configure JSF to only call the setters mapped to the fields that have changed in the front end? The reason for this is that I have a requirement by which I have to detect deltas on every persist and log them, more about which can be read in this question.
Maybe I didn't understand you clearly, but why are you mapping directly your entity beans to a JSF view ?! IMHO it would be better if you add managed beans between your JSF pages and the entities in order to better separate your business logic from data access.
Any way, I think the easiest solution to impelement for that case is by making use of Value Change Events which are invoked "normally" after the Process Validations phase (unless you make use of the immediate attribute).
The good news about Value Change Events (regarding your example) is they are invoked ONLY after you force form submit using JavaScript or Command components AND the new value is different from the old value.
So, as an example on how to use value change listeners, you can add valueChangeListner attribute to each of your JSF tags like following:
<h:inputText id="input" value="#{someBean.someValue}"
valueChangeListener="#{someBean.valueChanged} />
Then, implement your valueChanged() method to look something like:
public void valueChanged(ValueChangeEvent event) {
// You can use event.getOldValue() and event.getNewValue() to get the old or the new value
}
Using the above implementation, may help you to separate your logging code (it will be included in the listeners) from your managed properties setters.
NB: Value Change Listeners may also be implemetend otherwise using the f:valueChangeListener Tag, but this is not the best choice for your example (you can find some examples in the section below, just in case)
See also:
Valuechangelistener Doubt in JSF
JSF 2 valueChangeListener example
When to use valueChangeListener or f:ajax listener?

PostValidate datatable list values

I have a list of items that are being displayed using a h:datatable like so:
<p:dataTable value="#{myBean.instructorsList}" var="ins">
<p:column headerText="Name">
<h:inputText value="#{ins.name}"/>
</p:column>
</p:dataTable>
My spec is that I cannot allow a instructor to have the same name as another insturctor. So I need to have access to all the entire instructorList when it is submitted. I have attempted to validate using a postValidate f:event however due to the JSF lifecycle it does not update the model values till after the postValidation phase.
My attempt
<f:event listener="#{myBean.myMethod}" type="postValidate" />
Backing code
private List<instructors> instructorsList;
public void myMethod(ComponentSystemEvent event) {
// Attempting to use the instructorsList with new values. However, this
// is at the wrong stage
}
How would I write a validator to accomplish checking for duplicate instructor names?
Within a listener, use the getSubmittedValue method on HtmlInputText to pull the value straight off the component. Also, postValidate is semantically late to call problems on the validation process. Use the preValidate method instead. Altogether, you should have
public void myMethod(ComponentSystemEvent event) {
HtmlInputText txtBox = (HtmlInputText)event.getComponent();
String theValue = txtBox.getSubmittedValue().toString(); //the value in the textbox
//based on the outcome of your validation, you also want to do the following
FacesContext.getCurrentInstance().setValidationFailed(); //flag the entire request as failing validation
txtBox.setValid(false); //mark the component as failing validation
}
EDIT: This approach is heavily hinged on the premise that your users will be submitting only one row at a time. In the case where the entire table/column is being submitted in one request, you'll find that evaluating each input field on by one doesn't do much to prevent race conditions; you should be looking toward cross-field validation instead.
EDIT 2: I was mistaken, you cannot have race conditions when the event listener is being called. The listener is executed for each row, sequentially. This allows you to safely check each row (perhaps against a Map, for duplicates), without worrying about race conditions.

index of jsf component that fired event

This has to be a dumb question, but I can't seem to find the right keywords to google on: I have an action listener that can receive an event from any one of multiple checkboxes that were all generated from the same line of jsp in a dataTable. How can I tell from the action listener which one issued the event?
In particular, I need the index of the component so I can map it to an ordered list in the model. I know I can get the UIComponent object, and from there I can get the client ID of the component. And knowing that the client ID has the component's index embedded in it, yes I could do the sleazy thing, and parse the index from the client ID. But I know that would be a horrible, fragile and unmaintainable hack.
What's the right way to do this?
After an initial search, I think this could help you.
http://illegalargumentexception.blogspot.com/2009/02/jsf-working-with-component-ids.html
Have you tried to use f:param in addition to the checkbox values to pass custom parameters, so that would be more cleaner than working with ID's to manipulate business logic. ID.
Using the DataTables var attribute, you should be able to do this
<h:dataTable ... var="currentRow">
....
<h:selectBooleanCheckbox ... actionListener="#{blah.doThis}">
<f:attribute name="curRec" value="#{currentRow}" />
</h:selectBooleanCheckbox>
bean:
public void doThis(ActionEvent ae)
{
TreeMap myMap = (TreeMap)ae.getComponent().getAttributes().get("curRec");
...
}
Edit: The binding variable of your datatable should have the method getRowIndex();. That should give you the index of the record that caused the event in the table. I'm referencing an ICEfaces project, so I apologize if that isn't correct. Let me know, thx.

Resources