How to trigger action on primefaces datatable row expansion only not rowToggle - jsf

I need the action to be triggered when expanding a row only, not when collapsing it, so basically rowToggle event doesn't work for me as it executes in both expanding and collapsing events
<p:ajax event="rowToggle" listener="#{queryStudiesBean.onRowToggle}" />
I need somthing like this, but with event="rowExpansion", but no rowExpansion event exists, so how can I do this?

You should use visibility property of the ToggleEvent:
public void onRowToggle(org.primefaces.event.ToggleEvent event) {
if (event.getVisibility() == Visibility.VISIBLE) {
// Row was expanded
}
}

Related

ICEfaces (JSF) 3.3.0 SelectInputText Enter Key doesn't select the Item from the list

I am having some issues with ICEfaces 3.3.0 SelectInputText.
Following scenarios:
scenario 1:
typing "d" in the entry
I get the list of the SelecItems. (Dummy, dummy2 ...)
now when I select "Dummy" by clicking it with the left mouse key, the value aissigned to selectInputText.value is set to Dummy (expected behavior)
scenario 2:
typing "d" in the entry
I get the list of the SelecItems. (Dummy, dummy2 ...)
now when I select "Dummy" by scrolling with the courser-key on it and press Enter Key, I get the value set to "d" and not Dummy.?
scenario 3:
typing "d" in the entry
I get the list of the SelecItems. (Dummy, dummy2 ...)
now when I select "Dummy" by scrolling with the courser-key on it and press Ctrl + Enter Key, I get the value set to "Dummy". expected behavior.
I also add a actionListener to the selectInputText.actionListener to see what is going on:
in case of scenario 2 the actionListener called two times: checking the value in the first actionListener contains "d" and second following call contains "Dummy"
I know when you don't select anything from the drop-list and press the Enter-key, the value is set to the text entered in the selectInputText, which is also a expected behavior and is as documented, but in my case scenario 2
Why does the actionListener called two times? That is, the item is not selected by pressing Enter key at the first call?
Is this a Bug or did I miss something?
Thanks in advance!
Here is the code:
<ice:selectInputText
value="#{controller.selectedText}"
actionListener="#{controller.doSubmitText}"
textChangeListener="#{controller.textChangedEvent}"
rows="0"
width="300"
listVar="person"
listValue="#{controller.persons}">
<f:facet name="selectInputText">
<h:panelGrid id="f"
columns="2" width="100%"
columnClasses="col75,col25">
<ice:outputLabel value="#{person.name}"/>
<ice:outputLabel value="#{person.username}"/>
</h:panelGrid>
</f:facet>
</ice:selectInputText>
and here is the related part of the Bean (scope=session)
private List<SelectItem> persons;
public List<SelectItem> getPersons() {
return persons;
}
public void setPersons(List<SelectItem> persons) {
this.persons= persons;
}
private String selectedText = null;
public String getSelectedText() {
return selectedText;
}
public void setSelectedText(String selectedText) {
this.selectedText = selectedText;
}
public void textChangedEvent(TextChangeEvent ev) {
personlist = getfilteredList(ev.getNewValue().toString());
}
public void doSubmitText(ActionEvent event) {
System.out.println(selectedText);
}
The reason for your Scenario 2 behavior are the IceFaces Life Cycles and how events are processed. Listeners are alwayes called two times.
Considering you are using this code in a listener, its execution has been triggered by an event. Events have a phase which tell the framework in which part of the lifecycle you want them to be processed
You can read some more about the Lifecycles by googleing "JSF lifecycle"
For your special "problem" you have to check correct phase and set the value (put this at the beginnig of your listener method):
if (!event.getPhaseId().equals(PhaseId.INVOKE_APPLICATION)) {
event.setPhaseId(PhaseId.INVOKE_APPLICATION);
event.queue();
return true;
}

Issue with p:ajax event colReorder

Inside a p:dataTable i have some ajax events that display FacesMessages when i edit something
<p:ajax event="cellEdit" listener="#{userRegistrationController.cellEditAction}"
update=":currentUserForm:currentUsersFormMessages"/>
<p:ajax event="colResize" listener="#{userRegistrationController.colResizeAction}"
update=":currentUserForm:currentUsersFormMessages"/>
<p:ajax event="colReorder" listener="#{userRegistrationController.colReorderAction}"
update=":currentUserForm:currentUsersFormMessages"/>
The only one that's not working is the "colReorder" one, when i call the method i have javax.el.MethodNotFoundException: Method not found: com.mycompany.primeautosales.jsf.UserRegistrationController#476d042d.colReorderAction(javax.faces.event.AjaxBehaviorEvent) .
Here are the methods colResizeAction and colReorderAction, i don't get why one work and the other doesn't.
public void colResizeAction(ColumnResizeEvent event){
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
"the width of column "+event.getColumn()+" is now "+event.getWidth()
));
}
public void colReorderAction(ReorderEvent event){
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
"reordered "+event.getComponent().toString()));
}
Is there something wrong with ReorderEvent class ?
Try with the bean Action parameter ty change to action behavior like below code
public void onReorder(AjaxBehaviorEvent event) {
DataTable dataTable = (DataTable) event.getComponent();
List<UIColumn> columns = dataTable.getColumns();
//build new column order to store
for(UIColumn : column columns)
{
//read column names
}
//store list to db
}
for reference Click here
The problem is that the ajax event "colReorder" does not support the listener parameter org.primefaces.event.ReorderEvent. That's why you have this error! As the #Araf mentioned above, the AjaxBehaviorEvent event is supported by the colReorder event.

Update Primefaces selectOneMenu from JavaScript

I have a JSF form, that contains some JavaScript. When a specific input changes to a value >= 10 a selectOneMenu needs to dynamically change its option (which is yes or no).
My jQuery:
if ($("input[id*='inputBox']").val() >= 10) {
$("select[id*='selectOneMenu']").val("No");
} else {
$("select[id*='selectOneMenu']").val("Yes");
}
When I debug, the value in the selectOneMenu is changed correctly, but the UI component doesn't change its option. How do I tell the selectOneMenu to update its rendered value?
PrimeFaces SelectOneMenu is not a trivial select tag, it is a collection of divs put together to make it look like a select tag, use widgetVar.selectValue(val);
select tag is hidden inside the visible UI parts so that's why it is not working for you.
Your best bet will be to call a p:remoteCommand once the value should toggle. You will need to have the remoteCommand update your selectOneMenu ID (or IDs).
<p:remoteCommand name="setNo" actionListener="#{myBean.setNo}"
update="selectOneMenu" />
<p:remoteCommand name="setYes" actionListener="#{myBean.setYes}"
update="selectOneMenu" />
<SCRIPT>
var val="No"; //I'm assuming your initial value is "No"
if ($("input[id*='inputBox']").val() >= 10) {
if (val==="Yes") {
setNo();
val="No";
}
} else {
if (val==="No") {
setYes();
val="Yes";
}
}
</SCRIPT>
Then in your backing bean:
Map<String, String> selectBoxValues = ...
public void setNo() {
selectBoxValues.put("No", index);
}
[ditto for yes]
Of course, I've made up a bunch of variable names; you will have to change the text to suit your real variables.

How save or update single inputText field using ajax listener

I spent already more time as is good about some saving or updating issue in inputtext field, i go right to the point:
i have basic single input text with some basic attributtes
<h:inputText id="name" value="#{salesController.selectedSalesName}" />
here is a getter for inputText value
public String getSelectedSalesName(){
for(DealerListView dealer : dealerList){
if(dealer.getDealerId() == getSelectedDealerId()){
return dealer.getName();
}
}
return "";
}
nested in there i use ajax tag
<f:ajax event="change" render="name" listener="#{salesController.updateSelectedSalesName()}" />
a here is back bean method for updating a input text field
public void updateSelectedSalesName() {
DealerData dealDat = BeanFactory.getHotelDAOService(DealerData.class).findOne(selectedDealerId);
dealDat.setName(name);
BeanFactory.getHotelDAOService(DealerData.class).update(dealDat);
}
whole result of this is stack trace which say
value="#{salesController.selectedSalesName}": Property 'selectedSalesName' not writable on type sk.hotel.web.controller.SalesController
I know that something changes is need for that getter method but try some combinations without result which make corect update of value to database.
(I dont use any commands buttons for submit,update only response on pressing Enter in that inputText field.)
I want some guide how can be modified this save/update process whether on back-bean or jsf layout
or maybe someone solved similar situation already,and can share his solution.
Thanks all of you for advice posts.
Regards and nice day
First, add a field:
String selectedSalesName;
Add a setter and setter:
public String getSelectedSalesName() {
return selectedSalesName;
}
public void setSelectedSalesName(String selectedSalesName) {
this.selectedSalesName = selectedSalesName;
}
Add a ajaxListener(AjaxBehaviurEvent event) to create a new Dealer or Update current Dealer
public void ajaxListener(AjaxBehaviorEvent event) {
Dao dao = BeanFactory.getHotelDAOService(DealerData.class)
if (selectedDealerId == null) {
DealarData dealerData= new DealerData();
dealerDate.setName(getSelectedSalesName());
dao.add(dealerData);
setDealer(dealerData);
} else {
DealerData dealDat = dao.findOne(selectedDealerId);
dealDat.setName(name);
dao.update(dealDat);
}
}
A setter to the current dealer
int selectedDealerId;
public void setDealer(DealerData dealer) {
selectedDealerId = dealer.getId();
selectedSalesName = dealer.getName();
}
And the xhtml page:
<h:inputText value="#{salesController.selectedSalesName}" id="idSalesInput">
<a4j:ajax event="keyup" listener="#{salesController.ajaxListener}"
execute="idSalesInput"/>
</h:inputText>
Change "keyup" for the event you want to listen.
When you press a key, the listener is called, and the value of idSalesInput is submitted (the setSelectedSalesName() method is called here, for this reason you got the Property 'selectedSalesName' not writable exception),and the listener create or update a new DealerData.
Have a nice Day and sorry for my bad english!
Binding value in your inputText is two way, when it is rendered than getter is called to calculate value, when it is submited (like in your AJAX event) setter is called for that property to set value in your backing bean. So JSF tries to call setSelectedSalesName(String value). JSF can't write your property, which means can't call setter.
See also:
AJAX listener not being fired for inside

Event Function called before Setter

I have the following dropdown which list couple of cars, I have it so that it stores the value of selected item in a backbean variable and an event is fired so other dropdowns would fill up according to the selected value of this dropdown control as below:
<Td>
<h:selectOneMenu id="combocarList"
value="#{customerBean.selectedcar}"
styleClass="comboStyle"
valueChangeListener="#{customerBean.loadothercombos}"
onchange="document.forms[0].submit()"
>
<f:selectItem
itemLabel="-----------Select--------------"
itemValue="None" />
<f:selectItems value="#{customerBean.carsList}" />
</h:selectOneMenu>
</Td>
Problem is when an item selected from the above dropdown, the event loadothercombos is called before the setter which causes problems.
Note that the backbean customer is defined as:
<managed-bean-name>customerBean</managed-bean-name>
<managed-bean-class>com.theway.customer</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
The behaviour i see in debugging that when i select an item from dropdown:
1) Getter is called for selectedcar
2) Loadothercombos is called <------- This is called by the event
3) Setter is called for selectedcar
I cannot get it to call the setter before calling loadothercombos. Any insight would be appreciated. Thanks
Using valueChangeListener for this purpose has always been a hacky way. Basically, there are two ways to work around this "problem":
Call FacesContext#renderResponse() so that JSF will immediately move to the render response phase and thus the update model values (and invoke action) phase will be skipped:
public void loadothercombos(ValueChangeEvent event) {
selectedcar = (String) event.getNewValue();
loadOtherCombosBasedOn(selectedcar);
// ...
FacesContext.getCurrentInstance().renderResponse();
}
Queue the event to invoke action phase so that it does its job after the setter being called:
public void loadothercombos(ValueChangeEvent event) {
if (event.getPhaseId() == PhaseId.INVOKE_APPLICATION) {
loadOtherCombosBasedOn(selectedcar);
} else {
event.setPhaseId(PhaseId.INVOKE_APPLICATION);
event.queue();
}
}
If you're using JSF 2.0, then there's a much easier way to handle this with help of <f:ajax>:
<h:selectOneMenu id="combocarList"
value="#{customerBean.selectedcar}"
styleClass="comboStyle">
<f:selectItem
itemLabel="-----------Select--------------"
itemValue="None" />
<f:selectItems value="#{customerBean.carsList}" />
<f:ajax listener="#{customerBean.loadOtherCombos}" render="otherComboIds" />
</h:selectOneMenu>
with
public void loadothercombos() {
loadOtherCombosBasedOn(selectedcar);
}
Unrelated to the concrete problem: a "combobox" is the incorrect term for this dropdown element. A combobox is an editable dropdown, it's basically a combination of <input type="text"> and <select>. What you've there just renders alone <select> and those are just dropdowns, so call them as such as well.
Problem is when an item selected from the above dropdown, the event
loadothercombos is called before the setter
Well, is the expected JSF life cycle behavior. Your valueChangeListener="#{customerBean.loadothercombos}" is invoked during validation phase after a succesful conversion/validation of the submitted value and only when the submitted value differs from the initial value. After invoking the valueChangeListener, JSF will continue with conversion/validation of the next UIInput and when JSF implementation determines that the data is valid, then proceed to the next Update Model Values Phase invoking your setter method value="#{customerBean.selectedcar}"

Resources