Call method when clicking on p:selectOneButton [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 6 years ago.
I am trying to trigger a method doSomething() through p:selectOneButton. Though every attempt to do so fails.
As p:selectOneButton has no actionListener I thought on using p:ajax and point it to the method doSomething(), but while it compiles without errors it still doesn't trigger the desired method when I click on it.
Here is my code sample:
<h:form id="languageSelectionForm">
<p:selectOneButton value="#{language.selectedLanguage}">
<p:ajax event="change" listener="#{language.doSomething}" />
<f:selectItems value="#{language.languagesMap}" />
</p:selectOneButton>
</h:form>
How can I trigger doSomething() when clicking on p:selectOneButton?

I found the error!
To fill p:selectOneButton I used <f:selectItems value="#{language.languagesMap}" />. On the controller end I had a method that looked like this one:
public Map<String, LanguageSpec> getLanguagesMap() { ... }
and public a getter and public setter connected to the parameter for the selection:
private LanguageSpec selectedLanguage;
When I changed the second Map-argument from LanguageSpec to String and the same for the selectedLanguage parameter, the events perfomed and triggered doSomething().
Hence, without having checked, I assume that p:selectOneButton can only handle events when <f:selectItems value="#{language.languagesMap}" /> is filled with a Map where both the key and val are filled with String objects.
Special thanks to all the above helpers. By confirming that my example code worked when copy & pasting, I was able to test my code specifically for this issue.

Related

JSF h link takes last item in list instead of current

I got a list of objects displayed in a page.
This is the view:
<h:form>
<h:dataTable var="o" value="#{opleidingController.opleidingen}" border="0" >
<h:column>
<f:facet name="header">Code</f:facet>
<h:link value="#{o.opl_code}" outcome="#{opleidingController.getOpleidingByCode(o.opl_code)}" />
</h:column>
<h:column>
<f:facet name="header">Titel</f:facet>
<h:outputText value="#{o.opl_titel} "></h:outputText>
</h:column>
<h:column>
<f:facet name="header">Thema</f:facet>
<h:outputText value="#{o.opl_thema} "></h:outputText>
</h:column>
</h:dataTable>
</h:form>
This displays everything very well.
Like you can see I got the code part of the object set as a link.
With this code I get an object out of the database, from which I display the details.
The problem here is that every link displays the details of the last object of the list instead of the current object where I click the link.
This is the function I call (which works):
public String getOpleidingByCode(String code) {
this.opleiding = this.opleidingFacade.getOpleidingByCode(code);
return "details";
}
I hope any of this makes any sense?
Sorry if the solution is super clear but I am new to all of this.
Thanks in advance!
Kind regards
Deflandrex
EDIT:
This is the function that I use to call the first view (from which I provided the code)
public String getOpleidingenOpThema() {
this.opleidingen = this.opleidingFacade.getOpleidingenOpThema();
return "resultaat";
}
Both the functions are located in 1 controller.
What happens with the current code :
The outcome value is processed for each link element in the datatable sequentially by calling the opleidingController. getOpleidingByCode(o.opl_code). The backing bean method sets the this.opleiding value corresponding to the o.opl_code. Once all the links's outcome values are processed this.opleiding holds the value of the last o.opl_code. Hence, you are seeing last value from the list in the details page.
One Proposed solution:
The this.opleiding value should be set in the controller based on the o.opl_code when you process the details after clicking the link and not when the link is displayed and the outcome is set. You need to
Set outcome="details" in the h:link tag as this value is static and does not change based on any logic in the backing bean and remove method binding.
Pass the value of o.opl_code as a request parameter to the link as given below within the h:link tag.
<f:param name="opl_code" value="#{o.opl_code}"/>
Have the detail backing bean load the this.opleiding value based on the request parameter opl_code. This way you will have details for specific opl_code based on what link you click.

Assign a bean property to a JSF variable through a commandLink [duplicate]

This question already has answers here:
How can I pass selected row to commandLink inside dataTable or ui:repeat?
(4 answers)
Closed 6 years ago.
Basically what I have is a list called "mep", I display its values with commandlink and all i want is once you select a link to assign its value to my bean property "selectMep", the display part works pretty well and I'm struggling with the assignment part as I get an error which says that a String (the type of my bean property) cannot be casted to a UIcomponent, here's my code:
<ui:repeat var="mep" value="#{helloBean.mep}" >
<tr>
<td>#{mep}</td>
<h:commandLink value = "#{mep}" action="" binding="#{helloBean.selectMep}"/>
</tr> <br></br>
</ui:repeat>
Any suggestions?
I would suggest to use the action of the commandLink, like this:
<h:commandLink value="#{mep}" action="#{helloBean.selectMep(mep)}" />
And add a new method to your bean:
public void selectMep(String val) {
System.out.println(val);
}

Get id from current row dataTable to link JSF Primefaces Java [duplicate]

This question already has answers here:
How can I pass selected row to commandLink inside dataTable or ui:repeat?
(4 answers)
Closed 6 years ago.
How can i get Id of current Row p:dataTable primefaces to my link where is used this Id? Describe it (sorry for my English). My dataTable looks like on this picture:
http://www.image-share.com/igif-2333-105.html
When i click the button i want to get Id of row where is this button, for example row 1 have id 1, so when button 1 is clicked i must get ID = 1. Show how looks my link where need id:
http://'serverAddress'/myApplication/PDF?type=document&id="+id"
Variable id have type int and getters, setters in entity and bean. Button in JSF looks like below:
h:commandButton value="Print" action="#{printBean.print()}"/>
Method 'Print' initiate my link. Any ideas how to do this? Thanks for help.
You can use p:dataTable's rowIndexVar attribute.
Name of the iterator to refer each row index
Whose iterator name can be used in EL to get the Row Id
For Example:
if rowIndexVar="myId" then you can access each row Index using that iterator name in EL using #{myID}.
Example:
<p:dataTable rowIndexVar="rowId" value="..." var="...">
<p:column>
<h:commandLink action="#{...}">
<f:param name="id" value="#{rowId}" />
</h:commandLink>
</p:column>
</p:dataTable>
Get id in bean
map<String,String> par_map = new HashMap<String,String>(); par_map=FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
String id=par_map.get("id");

p:selectOneMenu get just first value from list primefaces JSF

i have p:selectOneMenu, all values are viewed correctly but just first on my list can be chosen for example, on my list i have e-mail addresses, i can choose everyone but mail is sending just on first of them on list. My JSF code:
<p:dataTable value="#{additionalOrdersBean.additionalOrdersList}"
var="additionalOrders" rowIndexVar="lp" id="myTable" editable="true>
<p:column>
<p:selectOneMenu id="recipient" value="#{additionalOrdersBean.mailTo}" converter="#{mailConverter}" required="true" requiredMessage="#{loc['fieldRequired']}">
<f:selectItems value="#{buildingBean.buildingList2}" var="mail" itemLabel="#{mail.mail1}" itemValue="#{mail.mail1}" />
<f:selectItems value="#{buildingBean.buildingList2}" var="mail" itemLabel="#{mail.mail2}" itemValue="#{mail.mail2}" />
<f:selectItems value="#{buildingBean.buildingList2}" var="mail" itemLabel="#{mail.mail3}" itemValue="#{mail.mail3}" />
</p:selectOneMenu>
<h:message for="recipient" style="color:red"/>
<h:commandButton value="#{loc['send']}" action="#{additionalOrdersBean.sendProtocol()}" onclick="sendProtocolDialog.hide()"/>
</p:column>
</p:dataTable>
My bean:
private String mail1;
private String mail2;
private String mail3;
public List<Building> getBuildingList2() {
buildingList2 = getBldRepo().findByLocationId(lid);
return buildingList2;
}
Can anyone know how to fix it? I wont to send e-mail on choosen address not just on first on my list. Thanks
You seem to expect that only the current row is submitted when you press the command button in the row. This is untrue. The command button submits the entire form. In your particular case, the form is wrapping the whole table and thus the dropdown in every single row is submitted.
However, the value attribute of all those dropdowns are bound to one and same bean property instead of to the currently iterated row.
The consequence is, for every single row, the currently selected value is set on the bean property, hereby everytime overriding the value set by the previous row until you end up with the selected value of the last row.
You've here basically a design mistake and a fundamental misunderstanding of how basic HTML forms work. You basically need to move the form to inside the table cell in order to submit only the data contained in the same cell to the server.
<p:dataTable ...>
<p:column>
<h:form>
...
</h:form>
</p:column>
</p:dataTable>
If that is design technically not an option (for example, because you've inputs in another cells of the same row, or outside the table which also need to be sent), then you'd need to bind the value attribute to the currently iterated row instead and pass exactly that row to the command button's action method:
<p:dataTable value="#{additionalOrdersBean.additionalOrdersList}" var="additionalOrders" ...>
<p:column>
<p:selectOneMenu value="#{additionalOrders.mailTo}" ...>
...
</p:selectOneMenu>
...
<h:commandButton value="#{loc['send']}" action="#{additionalOrdersBean.sendProtocol(additionalOrders)}" ... />
</p:column>
</p:dataTable>
It's by the way not self-documenting and quite confusing to have a plural in the var name. Wouldn't you rather call it additionalOrder? Or is the javabean/entity class representing a single additional order really named AdditionalOrders?
Unrelated to the concrete problem: doing business logic in getter methods is killing your application. Just don't do that. See also Why JSF calls getters multiple times.

JSF PrimeFaces inputText inside dataTable

JSF-2.0, Mojarra 2.1.19, PrimeFaces 3.4.1
Summary of the problem: Have a p:inputText inside p:dataTable and inputText action fired by p:remoteCommand which passes the dataTable row index as a parameter with f:setPropertyActionListener. But it always passes the last row of the dataTable, not the index of the row which includes currently clicked p:inputText.
As it can be seen from my previous questions, I am trying to use p:inputText as a comment taker for a status like in Facebook or etc. Implementation includes a p:dataTable. It's rows represents each status. Seems like:
<p:dataTable id="dataTable" value="#{statusBean.statusList}" var="status"
rowIndexVar="indexStatusList">
<p:column>
<p:panel id="statusRepeatPanel">
<p:remoteCommand name="test" action="#{statusBean.insertComment}"
update="statusRepeatPanel">
<f:setPropertyActionListener
target="#{statusBean.indexStatusList}"
value="#{indexStatusList}">
</f:setPropertyActionListener>
</p:remoteCommand>
<p:inputText id="commentInput" value="#{statusBean.newComment}"
onkeypress="if (event.keyCode == 13) { test(); return false; }">
</p:inputText>
</p:panel>
</p:column>
</p:dataTable>
Upper code says when the press enter key, fire p:remoteCommand which calls the insert method of the managed bean.
#ManagedBean
#ViewScoped
public class StatusBean {
List<Status> statusList = new ArrayList<Status>();
public int indexStatusList;
public String newComment
//getters and setters
public void insertComment() {
long statusID = findStatusID(statusList.get(indexStatusList));
statusDao.insert(this.newComment,statusID)
}
Let's debug together; assuming there are three statuses shown in the p:dataTable, click in the p:inputText which in the second status(index of 1), type "relax" and press the enter key.
In the debug console, it correctly shows "relax", but it finds the wrong status because indexStatusList has the value of 2 which belongs the last status in the p:statusList. It must be 1 which is the index of p:inputText that clicked on the dataTable row.
I think problem is about p:remoteCommand which takes the last index on the screen.
How it works?
Let's imagine there is a p:commandLink instead of p:remoteCommand and p:inputText:
<p:commandLink action=#{statusBean.insertComment>
<f:setPropertyActionListener target="#{statusBean.indexStatusList}"
value="#{indexStatusList}"></f:setPropertyActionListener>
This component successfully passes the indexStatusList as currently clicked one.
Conceptual problem in this solution lies in way how p:remoteCommand works. It creates JavaScript function whose name is defined in name attribute of p:remoteCommand. As you putted this in dataTable it will iterate and create JavaScript function called test as many times as there is rows in this table, and at the end last one will be only one. So, solution can be in appending index at the name of the remoteCommand but that is bad, because you will have many unnecessary JavaScript functions. Better approach would be to create one function an pass argument to it. So define remoteCommand outside of datatable:
<p:remoteCommand name="test" action="#{statusBean.insertComment}" update="statusRepeatPanel">
and call test function like this in your onkeypress event:
test([{ name: 'rowNumber', value: #{indexStatusList} }])
This will pass rowNumber parameter in your AJAX request. In backing bean's insertComment() method you can read this parameter and do with it anything you want:
FacesContext context = FacesContext.getCurrentInstance();
Map map = context.getExternalContext().getRequestParameterMap();
Integer rowNumber = Integer.parseInt(map.get("rowNumber").toString());
NOTE: as you are updating panel in each row, maybe you can change update attribute of remoteCommand to #parent so this will work for all rows.
EDIT: You can update the specific panel in specific row with following code in Java method:
RequestContext.getCurrentinstance().update("form:dataTable:" + rowNumber + ":statusRepeatPanel")

Resources