Start a method through a table row - ajax

I'm french, I will do in my best to speack english with you.
I have a datatable with books and information books.
I want my table to create a button for adding my book to my order (Order myOrder) but I can not, despite my attempts to do so.
My facelet :
<div class="divListLivres">
<h1>Liste des livres</h1>
<h:dataTable styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row" var="_book"
value="#{catalogueIBean.books}">
<h:column>
<f:facet name="header">Titre</f:facet>
<h:outputLabel value="#{_book.title}" />
</h:column>
<h:column>
<f:facet name="header">Editeur</f:facet>
<h:outputLabel value="#{_book.editor}" />
</h:column>
<h:column>
<f:facet name="header">Auteur</f:facet>
<h:outputLabel value="#{_book.author.firstName}" />
<h:outputLabel value=" #{_book.author.lastName}" />
</h:column>
<h:column>
<f:facet name="header">Prix unitaire</f:facet>
<h:outputLabel value=" #{_book.unitPrice}" />
<h:outputLabel value="€" />
</h:column>
</h:dataTable>
</div>
Can you help me? Either by redirecting the action to a method of my bean (CatalogueIBean whith method "addOrder(){}") making sure to add the line directly in my object "Order myOrder." Thanks !

you can easily add another column of a command button to your datatable in that way you will also have a button in each row which can redirect you to your required method
<p:column style="width:6%" headerText="Add to Order">
<p:commandButton id="addOrderButton"
action="#{catalogueIBean.addOrder}" immediate="true" ajax="true"
icon="ui-icon-folder-open">
<f:param name="id" value="#{_book.id}" />
</p:commandButton>
</p:column>
note: you can change the icon as you want or remove if you dont want an icon instead you can name the button by the value attribute of the button. Also if you dont want your button to be in your data table you can make a new form outside the form of data table and add your button there.
your backing bean should be
FacesContext context = FacesContext.getCurrentInstance();
Map requestMap = context.getExternalContext().getRequestParameterMap();
String value = (String) requestMap.get("id");
Integer id = Integer.parseInt(value);
now that you have the id of each row you can traverse to your required object

The fonctione "AddOrder" does not start but my method "init ()" yes.
I want to retrieve the "order" object of my line, I do not see how that is possible here.
It should incorporate something for the ajax work?
Here is the beginning of my bean:
#ManagedBean(name = "catalogueIBean")
#RequestScoped
public class CatalogueIBean {
#Inject
private FacesContext facesContext;
#Inject
private BookService bookService;
// ////////////////Variables de facelet//////////////////
private String title;
private String isbn13;
private Double price;
private int selectAuthor;
private List<Author> authors;
private String selectEditor;
private List<SelectItem> editorNames;
private List<Book> books;
private Book selectedBook;
// ////////////////Méthodes de facelet//////////////////
public String addOrder(/*parameter ??*/) throws Exception {
//add order of the line of datatable in my order (or create an orderLine)
return null;
}
// ////////////////Initialisation//////////////////
#PostConstruct
public void init() throws Exception {
.......
}
thank you

Related

Primefaces 8.0 Datatable with Dynamic Model and Columns

I have a primefaces dataTable that displays data from several database tables. A selection list allows the user to select the specific database table to display. It works as expected except when the dataTable filtering capability is used. For example, when a user selects 'DEPT' from the selection list, the dataTable is rendered with data from the DEPT table. The user can select other tables normally. However, if the user selects another table called 'EMP' after filtering, the dataTable fails to render with the following exception:
javax.el.PropertyNotFoundException: The class 'example.dto.Dept' does not have the property 'firstName'.
at javax.el.BeanELResolver.getBeanProperty(BeanELResolver.java:576)
at javax.el.BeanELResolver.getValue(BeanELResolver.java:291)
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:156)
Here's the .xhtml file:
<h:form prependId="false">
<p:outputLabel for="selTbl" value="Select a table:" />
<p:autoComplete id="selTbl" value="#{mainBean.selectedTable}"
completeMethod="#{mainBean.filterAuditTables}" cache="true" dropdown="true" effect="fade"
minQueryLength="3" forceSelection="true" size="35" style="margin-left: 10px;">
<p:ajax event="itemSelect" listener="#{mainBean.onTableSelect}" process="#this" update="#form" />
</p:autoComplete>
<p:dataTable id="audTblData" value="#{mainBean.data}" var="row"
filteredValue="#{mainBean.filteredData}" resizableColumns="true" resizeMode="expand"
sortMode="multiple">
<f:facet name="header">
<h:outputText value="#{mainBean.selectedTable}" />
</f:facet>
<p:columns value="#{mainBean.tableColumns}" var="col" sortBy="#{row[col.property]}"
filterBy="#{row[col.property]}" filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="#{col.header}" />
</f:facet>
<h:outputText value="#{row[col.property]}" />
</p:columns>
</p:dataTable>
</h:form>
MainBean.java:
#Named
#ViewScoped
public class MainBean implements Serializable {
private static final long serialVersionUID = 1L;
// these are used for the audited table selection list
private List<String> auditedTables;
private String selectedTable;
// these are used in the table that displays the audit data
private List<ColumnModel> tableColumns;
private List<Auditable> data;
private List<Auditable> filteredData;
#Inject
private AudviewService audviewService;
#PostConstruct
public void init() {
auditedTables = audviewService.getAuditedTables();
}
public List<String> filterAuditTables(String query) {
return auditedTables
.stream()
.filter(t -> t.contains(query.toUpperCase()))
.collect(Collectors.toList());
}
public void onTableSelect(SelectEvent<String> event) {
retrieveTableData();
}
public void retrieveTableData() {
List<String> columns = audviewService.listTableColumns(selectedTable);
// initialize columns for <p:dataTable>
tableColumns = new ArrayList<ColumnModel>();
for (String col : columns) {
tableColumns.add(new ColumnModel(col, AudviewUtil.columnToProperty(col)));
}
// retrieve data for the selected table
data = audviewService.getTableData(selectedTable);
}
/* getters and setters */
}
Note that Auditable is an interface implemented by Dept.java and Emp.java.
As you noticed, the problem is switching from a filtered or sorted datatable to another, if the filtered or sorted column is a field that isn't in the new selected class. An easy solution would be moving all the needed fields into the superclass Auditable.
Another approach is separating datatable resetting&updating in two steps, here a possible solution (I replace, for testing purpose, your service with static code, so there could be some errors adapting my solution to your code):
xhtml
<h:form id="formTbl" prependId="false">
<p:outputLabel for="selTbl" value="Select a table:" />
<p:autoComplete id="selTbl" value="#{mainBean.selectedTable}"
completeMethod="#{mainBean.filterAuditTables}" cache="true"
dropdown="true" effect="fade" minQueryLength="3"
forceSelection="true" size="35" style="margin-left: 10px;">
<p:ajax event="itemSelect" listener="#{mainBean.onTableSelect}"
process="#this" onstart="PF('vtWidget').clearFilters()" />
</p:autoComplete>
<p:remoteCommand name="btn" process="#this" update="audTblData" />
<p:dataTable id="audTblData" value="#{mainBean.data}" var="row"
filteredValue="#{mainBean.filteredData}" resizableColumns="true"
resizeMode="expand" sortMode="multiple" widgetVar="vtWidget">
<f:facet name="header">
<h:outputText value="#{mainBean.selectedTable}" />
</f:facet>
<p:columns value="#{mainBean.tableColumns}" var="col"
sortBy="#{row[col.property]}" filterBy="#{row[col.property]}"
filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="#{col.header}" />
</f:facet>
<h:outputText value="#{row[col.property]}" />
</p:columns>
</p:dataTable>
</h:form>
java
public void retrieveTableData() {
List<String> columns = listTableColumns(selectedTable);
// initialize columns for <p:dataTable>
tableColumns = new ArrayList<ColumnModel>();
for (String col : columns) {
tableColumns.add(new ColumnModel(col + " header", col));
}
// retrieve data for the selected table
data = getData(selectedTable);
DataTable dataTable = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent("formTbl:audTblData");
if (dataTable != null) {
dataTable.reset();
}
PrimeFaces.current().executeScript("btn()");
}
Pay attention, if you need also to manage pagination.

f:ajax firing only once

I have a a form loading a list from my database. I can update, and delete the row i select and that is working fine. Now I added a start and stop button to each row to enable start an engine from another application. Now what I want to do is when i click on start ,my engine would start based on that row and that row would hide the start button and show the stop button.
I have implemented ajax on those columns in the row but it updates all rows at once and the ajax only triggers once.
What am I doing wrong here and can you show me the best way to press on start and then hide my start-button and show my stop-button or press on stop and hide my stop-button and show my start-button on that particular row.
snippet of codes in my managedbean
#ManagedBean
#SessionScoped
public class HibernateController {
private ArrayList<IPAddress> ipAddresses;
private Logger logger = Logger.getLogger(getClass().getName());
private boolean isStarted = false;
private boolean isStopped = true;
public HibernateController(){
ipAddresses = new ArrayList<IPAddress>();
}
public boolean engineIsStarted() {
return isStopped;
}
public boolean engineIsStopped() {
return isStarted;
}
public void startEngine(AjaxBehaviorEvent event){
System.out.println("I am here and started");
isStarted = true;
isStopped = false;
}
public void stopEngine(AjaxBehaviorEvent event){
System.out.println("I am here and stopped");
isStopped = true;
isStarted = false;
}
Snippet of codes in my xhtml
<h:form>
<h:dataTable value="#{hibernateController.ipAddresses}" var="tempAddress"
styleClass="demo-table"
headerClass="demo-table-header"
rowClasses="demo-table-odd-row,demo-table-even-row">
<h:column>
<!-- the column header -->
<f:facet name="header">IP Adress</f:facet>
<!-- the value for each row -->
#{tempAddress.ipAddress}
</h:column>
<h:column>
<!-- the column header -->
<f:facet name="header">Port Number</f:facet>
<!-- the value for each row -->
#{tempAddress.portNumber}
</h:column>
<h:column>
<!-- the column header -->
<f:facet name="header">Action</f:facet>
<!-- the value for each row -->
<h:commandLink value="Update"
action="#{hibernateController.loadAddress(tempAddress.id)}"/>
|
<h:commandLink value="Delete"
onclick="if (!confirm('Are you sure you want to delete this address?')) return false"
action="#{hibernateController.deleteAddress(tempAddress.id)}"/>
</h:column>
<h:column>
<h:commandButton id="startButton" value="start" rendered="#{hibernateController.engineIsStarted()}">
<f:ajax event="click" execute="#this" listener="#{hibernateController.startEngine}" render="#all" />
</h:commandButton>
<h:commandButton id="stopButton" value="stop" rendered="#{hibernateController.engineIsStopped()}">
<f:ajax event="click" execute="#this" listener="#{hibernateController.stopEngine}" render="#all" />
</h:commandButton>
</h:column>
</h:dataTable>
</h:form>
Image of interface now

jsf inputText don't execute change listener event

i have two .xhtml pages with two similar inputText elements ("customer id" and "customer name"), in both pages the inputText for "customer id" launch a request ajax event to looking for the name of the customer and to put it in the inputText for "customer name".
when i run the web application and use the first pages everything work fine, but if i don't use the first page and go to the second page (via commandlink in first page) without use the first page then the inputText for search the customer name don't work, indeed not enter to the testBean2.searchCustId method.
the code:
first page
<h:form>
<h:commandLink action="page2">PAGE 2</h:commandLink><br/>
<h:outputText value="customer id: "/>
<h:inputText id="custoId" label="CUSTOMER_ID" value="#{testBean.custId}" required="true">
<a4j:ajax event="change" listener="#{testBean.searchCustId(testBean.custId)}" render="custoName"/>
<f:validateLength minimum="1" maximum="12"/>
</h:inputText>
<rich:message for="custoID" ajaxRendered="true"/>
<h:outputText value="Customer name: "/>
<h:inputText id="custoName" label="CUSTOMER_NAME" value="#{testBean.custName}"/>
<rich:message for="custoName" ajaxRendered="true"/>
</h:form>
second page
<h:form>
<h:outputText value="customer id: "/>
<h:inputText id="custoId2" label="CUSTOMER_ID2" value="#{testBean2.custId}" required="true">
<a4j:ajax event="change" listener="#{testBean2.searchCustId(testBean2.custId, 0)}" render="custoName2"/>
<f:validateLength minimum="1" maximum="12"/>
</h:inputText>
<rich:message for="custoId2" ajaxRendered="true"/>
<h:outputText value="customer name: "/>
<h:inputText id="custoName2" label="CUSTOMER_NAME2" value="#{testBean2.custName}"/>
<rich:message for="custoName2" ajaxRendered="true"/>
</h:form>
now jsf managed bean
testBean
public class TestBean {
private String custId;
private String custName;
public TestBean() {
}
//getter and setter
public void searchCustId(String ced){
custName = ced + "- SOME CUSTOMER NAME"; //THIS IS FOR TESTING
}
}
testBean2
public class TestBean2 {
private String custId;
private String custName;
public TestBean2() {
}
//getter and setter
public void searchCustId(String ced, int que){
custName = ced + " - " + que; //THIS IS FOR TESTING
}
}
what may be happening?
i'm new on this and my english is not good :)
You can use f:setPropertyActionListener.
<a4j:ajax event="change" listener="#{myBean.listener}">
<f:setPropertyActionListener target="#{myBean.someProperty}" value="your_value_here"/>
</a4j:ajax>
But from your code it looks like you are trying to pass the very one value that's used on h:inputText, that's not necessary:
<h:inputText id="custoId" label="CUSTOMER_ID" value="#{testBean.custId}" required="true">
<a4j:ajax event="change" listener="#{testBean.searchCustId}" render="custoName"/>
<f:validateLength minimum="1" maximum="12"/>
</h:inputText>
After Ajax event the values testBean.searchCustId will automatically be updated on Managed bean after passing the validation, so your listener could be:
public class TestBean {
private String custId;
private String custName;
public TestBean() {
}
//getter and setter
public void searchCustId(){
custName = custId + "- SOME CUSTOMER NAME"; //THIS IS FOR TESTING
}
}

Ajax in JavaServer Faces

I’m trying to use ajax in jsf.
So, I have inputtextarea and datatable:
<h:form>
<h:inputTextarea id="mailstextarea" style="width:100%" value="#{newMembersBean.newMembersStr}">
<f:ajax event="keyup" render="newmembertable" execute="mailstextarea" />
</h:inputTextarea>
<h:dataTable id="newmembertable" styleClass="tableWidth" value="#{newMembersBean.newMembers}" var="member">
<h:column>
<f:facet name="header">#{msgs.name}</f:facet>
#{member.name}
</h:column>
<h:column>
<f:facet name="header">#{msgs.surename}</f:facet>
#{member.sureName}
</h:column>
<h:column>
<f:facet name="header">#{msgs.email}</f:facet>
#{member.email}
</h:column>
<h:column>
<f:facet name="header">#{msgs.phone}</f:facet>
#{member.phone}
</h:column>
</h:dataTable>
<h:commandButton type="submit" value="#{msgs.add}"/>
</h:form>
I want to change newMembersBean.newMembers List (and datatable newmembertable) on every value change in textarea…
In my bean I’m trying to do somethink like this (now only for testing, I want to show all users, if user have typed more then 3 characters):
#Named
#ConversationScoped
public class NewMembersBean implements Serializable {
private List<UsersEntity> newMembers = new ArrayList<UsersEntity>();
private String newMembersStr = "";
......
public List<UsersEntity> getNewMembers() {
UsersDao ud = new UsersDao();
if(newMembersStr.length() > 3)
{
newMembers = ud.getAllUsers();
}
return newMembers;
}
.....
}
But when I’m typing text in textare nothing happens.
Please help.
Thanks.

<p:ajax> Unable to attach <p:ajax> to non-ClientBehaviorHolder parent

I use JSF 2 , primefaces 4.0 and i try to use DataTable - In-Cell Editing as it's produced in primefaces showcase, but i have an error althought i copied the same example shown in showcase
the error is
<p:ajax> Unable to attach <p:ajax> to non-ClientBehaviorHolder parent
this is the xhtmlpagecode
<rich:panel style="width : 800px; height : 551px; " >
<f:facet name="header" >
<h:outputText value="Tableau des articles" align="center" style="FONT-SIZE: small;"/>
</f:facet>
<h:form id="form">
<p:dataTable id="cars" var="car" value="#{articlesbean.LMatpilotaccess1}" editable="true" editMode="cell" widgetVar="carsTable">
<f:facet name="header">
Matériel du pilotage et accessoires
</f:facet>
<p:growl id="messages" showDetail="true"/>
<p:contextMenu for="cars" widgetVar="cMenu">
<p:menuitem value="Edit Cell" icon="ui-icon-search" onclick="PF('carsTable').showCellEditor();return false;"/>
<p:menuitem value="Hide Menu" icon="ui-icon-close" onclick="PF('cMenu').hide()"/>
</p:contextMenu>
<p:column headerText="Serie" style="width:25%">
<p:ajax event="cellEdit" listenner="#{articlesbean.onCellEdit}" update=":form:messages" />
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{car.serie}" /></f:facet>
<f:facet name="input"><p:inputText id="modelInput" value="#{car.serie}" style="width:96%"/></f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
</h:form>
</rich:panel>
and this is my bean
#ManagedBean(name="articlesbean")
#ViewScoped
public class ArticlesBean implements Serializable{
#Inject
private ArticlesDAO articleDAO;
#Inject
private Matpilotaccess1 matpilotaccess1;
#Inject
private Matpilotaccess2 matpilotaccess2;
#Inject
private Poteaux poteaux ;
#Inject
private Travgc1 travgc1;
#Inject
private Travgc2 travgc2;
#Inject
private Travresurbain travresurbain;
private List LMatpilotaccess1 = new ArrayList();
private List LMatpilotaccess2 = new ArrayList();
private List LPoteaux = new ArrayList();
private List LTravgc1 = new ArrayList();
private List LTravgc2 = new ArrayList();
private List LTravresurbain = new ArrayList();
public void onCellEdit(CellEditEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
if(newValue != null && !newValue.equals(oldValue)) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Cell Changed", "Old: " + oldValue + ", New:" + newValue);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
//// Getters and setters
You nested the <p:ajax> inside a <p:column>. The <p:ajax> requires to be nested in a component implementing the ClientBehaviorHolder interface. However, the Column component class behind <p:column> does not implement it. The DataTable component class behind <p:dataTable> implements it.
You should be nesting <p:ajax> inside <p:dataTable> instead:
<p:dataTable ...>
<p:ajax ... />
<p:column ...>
...
</p:column>
</p:dataTable>
Exactly as demonstrated on their showcase site. In other words, your statement
althought i copied the same example shown in showcase
is actually not true.

Resources