The short version of my problem is that the inputtext will not change the value in bean after I modified the value from the bean.
The longer version:
There is a form in which is a dataTable with user information; some inputTexts, and two buttons. If you fill the inputTexts, a new user will be created with the given data, and appears in dataTable - this works fine, I can create as many users as I can.
The tricky part is if you select a row from the dataGrid, the user information has to appear in the inputText fields - this works fine - so the admin can modify them. But after changing the inputText values in the bean, if the admin changes someting in the inputText, the value "will not follow" tha changes, the value remains the same. What could I do wrong?
The JSF page looks like this:
<html>
<h:body>
<h:form style="font-size:14px;" id="setupform">
...
<p:panel header="Edit users" id="userAddingPanel" rendered="#{settingsbean.validLogin}">
<p:panelGrid columns="2" id="userAddingGrid">
<p:outputLabel value="User Name: " />
<p:inputText id="userName" value="#{settingsbean.userName}" />
<p:outputLabel value="User Password: " />
<p:password id="userPass" value="#{settingsbean.userPassword}" />
<p:outputLabel value="E-mail address: " />
<p:inputText id="userMailAddress" value="#{settingsbean.mailAddress}" />
<p:outputLabel id="userDelete" value="Inactivate User: " />
<p:selectBooleanCheckbox id="isUserDeleted" value="#{settingsbean.deletedUser}" />
<p:commandButton id="addUser" value="Create User" update="userAddingGrid" icon="ui-icon-disk" action="#{settingsbean.addNewUser}" />
<p:commandButton id="modifyUser" value="Modify User" icon="ui-icon-wrench" update="userAddingGrid" action="#{settingsbean.updateUser}" process="setupform"/>
</p:panelGrid>
<br/>
<p:dataTable id="usersTable" var="users" value="#{settingsbean.userList}" tableStyle="overflow: auto;" stickyHeader="true" selectionMode="single" rowKey="#{users.id}" selection="#{settingsbean.selectedUser}">
<p:ajax event="rowSelect" update=":setupform:userName, :setupform:userName,
:setupform:userPass, :setupform:userMailAddress, :setupform:isUserDeleted" />
<p:column headerText="#ID">
<h:outputText value="#{users.id}" />
</p:column>
<p:column headerText="Name">
<h:outputText value="#{users.loginName}" />
</p:column>
...
</p:dataTable>
</p:panel>
</h:form>
</h:body>
</html>
And my bean looks like this:
#ManagedBean(name ="settingsbean")
#ViewScoped
public class SettingsBean {
private String userName;
private String userPassword;
private boolean deletedUser;
private List<UserDTO> userList;
private UserDTO selectedUser;
/*with getters and setters, what is uncenventional is this setter*/
public void setSelectedUser(UserDTO selectedUser) {
/*if admin selects/unselects a user from dataTable*/
this.selectedUser = selectedUser;
/*if unselect user*/
if(selectedUser == null){
userName = "";
mailAddress = "";
deletedUser = false;
/*if selects user*/
}else {
userName = selectedUser.getLoginName();
mailAddress = selectedUser.getMailAddress();
deletedUser = selectedUser.getDeleted();
}
}
...
public void addNewUser(){
//creates a new user in DB
}
public void updateUser(){
//will update user in DB
}
}
You have to process the components that you want to be updated
<p:commandButton id="modifyUser" value="Modify User" icon="ui-icon-wrench" update="userAddingGrid" action="#{settingsbean.updateUser}" process="userAddingGrid"/>
Related
I have a Users table. Added, view and delete work. But I have problem to edit.
My list page:
<h:form id="form">
<p:dataTable styleClass="table" value="#{userMB.allAdmins}" var="admin" paginator="true" rows="15" rowKey="#{admin.id}" selection="#{userMB.user}" selectionMode="single">
<f:facet name="header">
Lista administratorów
</f:facet>
<p:column headerText="#{msg.firstName}">
<h:outputText value="#{admin.firstName}" />
</p:column>
<p:column headerText="#{msg.lastName}">
<h:outputText value="#{admin.lastName}" />
</p:column>
<p:column headerText="#{msg.personalId}">
<h:outputText value="#{admin.personalId}" />
</p:column>
<f:facet name="footer">
<p:commandButton id="viewButton" value="#{msg.info}" icon="ui-icon-search"
update=":form:display" oncomplete="userDialog.show()"/>
<p:commandButton action="#{userMB.createStart()}" value="#{msg.add}" icon="ui-icon-plus" />
<p:commandButton action="#{userMB.editStart()}" value="#{msg.edit}" >
<f:setPropertyActionListener target="#{userMB.user}" value="#{userMB.user}" />
</p:commandButton>
<p:commandButton action="#{userMB.deleteUser()}" value="#{msg.delete}" icon="ui-icon-close"/>
</f:facet>
</p:dataTable>
<p:dialog id="dialog" header="Administrator" widgetVar="userDialog" resizable="false"
width="300" showEffect="clip" hideEffect="explode">
<h:panelGrid id="display" columns="2" cellpadding="4">
<f:facet name="header">
<p:graphicImage value="./../../images/person4.png" width="150" height="150"/>
</f:facet>
<h:outputText value="#{msg.firstName}" />
<h:outputText value="#{userMB.user.firstName}" />
<h:outputText value="#{msg.lastName}" />
<h:outputText value="#{userMB.user.lastName}" />
<h:outputText value="#{msg.personalId}" />
<h:outputText value="#{userMB.user.personalId}" />
</h:panelGrid>
</p:dialog>
</h:form>
I want to send the selected user on the next page:
I use aciontListener:
<p:commandButton action="#{userMB.editStart()}" value="#{msg.edit}" >
<f:setPropertyActionListener target="#{userMB.user}" value="#{userMB.user}" />
</p:commandButton>
My edit page where I want to send user:
<h:form>
<div id="userPanel">
<h:inputHidden value="#{userMB.user}" />
<p:panel id="panelUser" header="Edytuj administratora" >
<div id="panelImage">
<img src="./../../images/person4.png" alt="person" width="150px" height="130px"/>
</div>
<h:panelGrid columns="3">
<p:outputLabel for="firstName" value="#{msg.firstName}"></p:outputLabel>
<p:inputText id="firstName" value="#{userMB.user.firstName}" label="#{msg.firstName}" required="true">
<f:validator validatorId="nameValidator" />
<p:ajax update="msgFristName" event="keyup" />
</p:inputText>
<p:message for="firstName" id="msgFristName"/>
<p:outputLabel for="lastName" value="#{msg.lastName}"></p:outputLabel>
<p:inputText id="lastName" value="#{userMB.user.lastName}" label="#{msg.lastName}" required="true">
<f:validator validatorId="nameValidator" />
<p:ajax update="msgLastName" event="keyup" />
</p:inputText>
<p:message for="lastName" id="msgLastName"/>
<p:outputLabel for="personalId" value="#{msg.personalId}"></p:outputLabel>
<p:inputText id="personalId" value="#{userMB.user.personalId}" label="#{msg.personalId}" required="true">
<f:validator validatorId="personalIdValidator" />
<p:ajax update="msgPersonalId" event="keyup" />
</p:inputText>
<p:message for="personalId" id="msgPersonalId"/>
<p:outputLabel for="password" value="#{msg.password}"></p:outputLabel>
</p:panel>
</div>
</h:form>
I added: <h:inputHidden value="#{userMB.user}" /> but I do not see data user, only empty field. How do I send this person? I used once this method in other project, a little different without primefaces and it worked. Why now does not work?
Method editStart:
public String editStart() {
return "editStart";
}
faces-config:
<navigation-case>
<from-outcome>editStart</from-outcome>
<to-view-id>/protected/admin/adminEdit.xhtml</to-view-id>
<redirect/>
</navigation-case>
When I'm on the side adminEdit I edited the pool and do editUser method:
public String editUser() {
FacesContext context = FacesContext.getCurrentInstance();
Map requestParameterMap = (Map) context.getExternalContext().getRequestParameterMap();
try {
String userRole = requestParameterMap.get("userRole").toString();
String active = requestParameterMap.get("active").toString();
Boolean act = Boolean.parseBoolean(active);
user.setRole(userRole);
user.setActive(act);
userDao.update(user);
} catch (EJBException e) {
sendErrorMessageToUser("Edit error");
return null;
}
sendInfoMessageToUser("Account edited");
return user.getRole() + "List";
}
My method editStart use only for navigation.
You can either consider Przemek's answer or use one of the 4 ways of passing a parameter to a backing bean.
1. Method expression
2. f:param
3. f:atribute
4. f:setPropertyActionListener
For very well explained full explanation refer to this
It has easy to understand examples. Take a look and pick what fits your needs.
Or simply:
In the actual managed bean...
public String navigationButtonListener(User parameter) {
FacesContext.getCurrentInstance().getExternalContext().getRequestMap()
.put("parameterAttribute", parameter);
return "my-destination-page";
}
In the destination managed bean...
#PostConstruct
public void init(){
myAttribute= (User) FacesContext.getCurrentInstance()
.getExternalContext().getRequestMap().get("parameterAttribute");
}
Good Luck!
You can pass your userid through the session.
Add a parameter to your commandLink
<p:commandButton action="#{userMB.editStart()}" value="#{msg.edit}>
<f:param name="userId" value="#{userMB.user.id}" />
</p:commandButton>
In your backing bean do this
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest myRequest = (HttpServletRequest)context.getExternalContext().getRequest();
HttpSession mySession = myRequest.getSession();
Integer userId = Integer.parseInt(myRequest.getParameter("userId"));
After that you can reload the user you want to edit with the Id you got
I have a web application which have to implement login. user provide username and pwd after authenticating user should redirect to page which they have privilages pages are differant from user to user. Sometimes 2 or more users can get same page but available data should differant for do this I have pass users privilage ID(divisionId) to other beans
for now i have tried URL tagging parameter tagged to URL and dirrect to page successfully but I can't take it to bean variable.
Itried this with p:Button then textbox inputs won't get to bean class to execute the method when button click.
xhtml code -
<h:body>
<p:growl id="growl" showDetail="true" life="3000" />
<p:dialog id="dialog" header="Login" widgetVar="dlg" visible="true" closable="false" >
<h:form id="form">
<h:panelGrid columns="2">
<h:outputLabel for="username" value="Username: " />
<p:inputText id="username" value="#{loginBean.username}"
required="true" requiredMessage="Enter Username"/>
<h:outputLabel for="password" value="Password: " />
<p:password id="password" value="#{loginBean.password}"
required="true" requiredMessage="Enter Password"/>
</h:panelGrid>
<p:commandButton id="LoggingButton" value="Login" action="#{loginBean.doLogin()}"
update=":growl" oncomplete="handleLoginRequest(xhr, status, args),">
</p:commandButton>
</h:form>
</p:dialog>
</h:body>
loginbean-
public class LoginBean{
private String username;
private String password;
private int divisionId;
/**
* Creates a new instance of loginBean
*/
public LoginBean() {
}
public String doLogin() {
DbUser du = new DbUser();
divisionId = du.ValidateUser(username, password);
if(divisionId==0)
addMessage("Invalied username or password", false);
else{
if(divisionId==1){
// return "superuser.xhtml?faces-redirect=true";
return "superuser.xhtml?test="+divisionId+"faces-redirect=true";
//superAdmin
}
else if(divisionId==2||divisionId==3){
// return "engadmin_create_div.xhtml?faces-redirect=true";
return "engadmin_create_div.xhtml?test="+divisionId+"faces-redirect=true";
//ENG/IT ADMIN
}
else{
// return "viewonly_user.xhtml?faces-redirect=true";
return "viewonly_user.xhtml?test="+divisionId+"faces-redirect=true";
//View only users
}
}
return null;
}
I think that work :)
<p:growl id="growl" showDetail="true" life="3000" />
<p:dialog id="dialog" header="Login" widgetVar="dlg" visible="true" closable="false" >
<h:form id="form">
<h:panelGrid columns="2">
<h:outputLabel for="username" value="Username: " />
<p:inputText id="username" value="#{loginBean.username}"
required="true" requiredMessage="Enter Username"/>
<h:outputLabel for="password" value="Password: " />
<p:password id="password" value="#{loginBean.password}"
required="true" requiredMessage="Enter Password"/>
</h:panelGrid>
<p:commandButton id="LoggingButton" value="Login" actionListener="#{loginBean.doLogin()}">
</p:commandButton>
</h:form>
</p:dialog>
</h:body>
Bean
public class LoginBean{
private String username;
private String password;
private int divisionId;
/**
* Creates a new instance of loginBean
*/
public LoginBean() {
}
public static void redirect(String strDes) throws IOException {
ExternalContext ext = FacesContext.getCurrentInstance().getExternalContext();
ext.redirect(ext.getRequestContextPath() + strDes);
}
public void doLogin() {
DbUser du = new DbUser();
divisionId = du.ValidateUser(username, password);
if(divisionId==0)
addMessage("Invalied username or password", false);
else{
if(divisionId==1){
LoginBean.redirect("superuser.xhtml?test="+divisionId+"faces-redirect=true");
//superAdmin
}
else if(divisionId==2||divisionId==3){
LoginBean.redirect("engadmin_create_div.xhtml?test="+divisionId+"faces-redirect=true");
//ENG/IT ADMIN
}
else{
LoginBean.redirect("viewonly_user.xhtml?test="+divisionId+"faces-redirect=true");
//View only users
}
}
}
you get parameter from bean:
Map<String,String> params =
FacesContext.getExternalContext().getRequestParameterMap();
String action = params.get("test");
I have a form that user should enter some values to get some info from a web service. Firstly user fulfills the form and then as he clicks the request button webservice is called. Until here everything works nicely. But as the webservice returns the info, I have to re-render the datatable with the new data. Here is my page:
<h:body>
<h:form id="formCus">
<h:outputLabel value="Müşteri Tipi: *"/>
<p:selectOneMenu id="customerType" value="#{customerService.musteriTipi}" style="width: 39%">
<f:selectItem itemLabel="" itemValue=" " />
<f:selectItem itemLabel="Bireysel" itemValue="BIREYSEL" />
<f:selectItem itemLabel="Tüzel" itemValue="TUZEL" />
<f:selectItem itemLabel="Yabancı" itemValue="YABANCI" />
<p:ajax event="change" update="#{customerService.musteriTipi}"/>
</p:selectOneMenu>
<h:outputLabel value="Ad/Firma Adı: *" for="customerName" />
<p:inputText id="customerName" value="#{customerService.adFirmaAdi}" title="Müşteri adı." >
<p:ajax event="change" update="#{customerService.adFirmaAdi}" />
</p:inputText>
<h:outputLabel value="Soyad/Ünvan: *" for="customerSurname" />
<p:inputText id="customerSurname" value="#{customerService.soyadUnvan}" title="Müşteriye ait soyad/ünvan." >
<p:ajax event="change" update="#{customerService.soyadUnvan}" />
</p:inputText>
<h:outputLabel value="TC Kimlik No: *" />
<p:inputText id="customerTC" value="#{customerService.tcKimlikNo}" title="TC Kimlik numarasını buraya girin.TC numarası sadece sayılardan oluşmalıdır." >
<p:ajax event="change" update="#{customerService.tcKimlikNo}" partialSubmit="true" process="#this"/>
</p:inputText>
<h:outputLabel value="Vergi No:" />
<p:inputText id="customerVergi" value="#{customerService.vergiNo}" title="TC Kimlik numarasını buraya girin.TC numarası sadece sayılardan oluşmalıdır." >
<p:ajax event="change" update="#{customerService.vergiNo}" partialSubmit="true"/>
</p:inputText>
<h:outputLabel value="Müdürlük Kodu: *" />
<p:inputText id="departmantId" value="#{customerService.mudurlukKodu}" title="Müdürlük kodunu buraya girin.Müdürlük kodu sadece sayılardan oluşmalıdır." >
<p:ajax event="change" update="#{customerService.mudurlukKodu}" partialSubmit="true"/>
</p:inputText>
<h:outputLabel value="Müşteri Kodu: " />
<p:inputText id="customerId" value="#{customerService.musteriKodu}" title="Müdürlük kodunu buraya girin.Müdürlük kodu sadece sayılardan oluşmalıdır." >
<p:ajax event="change" update="#{customerService.musteriKodu}" />
</p:inputText>
<h:outputLabel value="E-Posta Adresi: " />
<p:inputText id="customerMail" value="#{customerService.mail}" title="Müşteriye ait e-mail adresini buraya girin." >
<p:ajax event="change" update="#{customerService.mail}" partialSubmit="true"/>
</p:inputText>
<h:outputText value=" "/>
<p:commandButton id="query" value="Müşteri Sorgula" actionListener="#{customerService.request}" async="true" onsuccess="panelwv.show()">
<f:ajax execute="#form" render=":personList" ></f:ajax>
</p:commandButton>
</h:form>
<h:panelGrid columns="5">
<h:outputText value=""/>
<h:outputText value=""/>
<p:panel widgetVar="panelwv" visible="false" closable="true" header="Sorgu Yapılıyor...">
<p:graphicImage value="/resources/images/ajaxloadingbar.gif" />
</p:panel>
<h:outputText value=""/>
<h:outputText value=""/>
</h:panelGrid>
<h:outputText value="Bulunan Müşterilere Ait Bilgiler:" />
<h:form id="personList" rendered="#{not empty customerService.musteriKodu}">
<p:dataTable value="#{customerService.customer}" var="item" id="persontable" emptyMessage="Henüz müşteri eklemediniz.">
<p:column headerText="Müşteri/Firma ID">
#{item.customerId}
</p:column>
<p:column headerText="Ad/Firma Adı">
#{item.customerName}
</p:column>
<p:column headerText="Soyad/Ünvan" >
#{item.customerSurname}
</p:column>
<p:column headerText="Müşteri Tipi" >
#{item.customerType}
</p:column>
<p:column headerText="Telefon" >
#{item.customerTel}
</p:column>
<p:column headerText="Adres">
#{item.customerAddress}
</p:column>
<p:column headerText="E-Posta">
#{item.customerMail}
</p:column>
</p:dataTable>
</h:form>
</h:body>
And here is my back bean:
//some getter and setters
List<Customers> customer = new ArrayList<Customers>();
public List<Customers> getCustomer() {
return customer;
}
public void setCustomer(List<Customers> customer) {
this.customer = customer;
}
public String request() {
final RequestContext context = RequestContext.getCurrentInstance();
//System.out.println("Progress...");
//musteriSorgula(musteriSorgulaKriter());
new Thread(new Runnable() {
public void run() {
try {
musteriKodu = String.valueOf(musteriSorgula(musteriSorgulaKriter()).getMusteriBilgisi().getMusteriKodu());
List<TelefonBilgisi> tel_result = telefonSorgula(telefonSorgulaKriter(musteriKodu)).getMusteriTelefonListesi();
//telefon = tel_result.getMusteriTelefonListesi().get(0).getTelefonNo();
if (tel_result.size() > 0) {
for (TelefonBilgisi t : tel_result) {
telefon = t.getTelefonNo();
}
} else {
telefon = "No telephone.";
}
List<UavtAdresBilgisi> uavt_result = uavtAdresSorgula(uavtAdresSorgulaKriter(musteriKodu)).getMusteriUavtAdresListesi();
if (uavt_result.size() > 0) {
for (UavtAdresBilgisi u : uavt_result) {
adres = String.valueOf(u.getSehir()) + ", " + String.valueOf(u.getBucak()) + ", " + String.valueOf(u.getKasaba());
}
} else {
adres = "No address.";
}
Customers cust = new Customers(musteriTipi, BigInteger.valueOf(Long.valueOf(musteriKodu)), adFirmaAdi, soyadUnvan, telefon, adres, mail, projectId);
if (!customer.contains(cust)) {
customer.add(cust);
System.out.println("Customer has been added.");
} else {
System.out.println("Customer is still in the list.");
}
} catch (Exception ex) {
Logger.getLogger(CustomerService.class.getName()).log(Level.SEVERE, null, ex);
context.execute("alert('Try again.')");
}
}
}).start();
context.execute("panelwv.close()");
return "";
}
The back bean could connect to webservice and gether the info, I can see that in the logs. In the beginning my datatable is empty. What I want is to show the new data as the webservice responses. context.update("personList") doesn't work when I place it below:
customer.add(cust);
If someone could help me I would be greatly appriciated.
<f:ajax execute="#form" render=":personList" ></f:ajax>
Make a change as
<f:ajax execute="#form" update="persontable" render=":personList" ></f:ajax>
Ok so what you want to do is to force the client to update the data table from your server. Take a look at comet and push technology and also (if you don't need to support older browsers) WebSocket.
If you google around you'll find tutorials on how to do it using JSF. And as you are using Primefaces, not that this library has comet support: checkout p:push and atmosphere support.
This problem is easy to solve if you use RichFaces
I would prefer using RemoteCommand component as #Ömer said.
Try use it at the end of the thread(inside the thread braces) with context.execute("updater();");
I am using Primefaces AutoComplete and I am getting records from database using Hibernate.
I am able to select values from database when I type in text. What I would like to achieve is when I select a name when I type characters, I would want my other columns in jsf page to get populated. E.g When I select employee name "SMITH" I want employee number, department to get filled with SMITH's employee number and department.
I have the following in jsf page.
<p:autoComplete value="#{myMB.selectedEmployee}"
id="basicPojo" minQueryLength="3"
completeMethod="#{myMB.complete}" var="p"
itemLabel="#{p.empName}"
converter="#{myconverter}"
forceSelection="true" >
<h:outputLabel value="Emp Number" />
<h:outputText value="#{p.employeeNumber}" />
<h:outputLabel value="Department" />
<h:outputText value="#{p.employeeDepartment}" />
</p:autoComplete>
When I select a name, other fields are not getting displayed.
What could be the reason for this? How can I achieve the desired result?
Any help is highly appreciated.
Edit 1
<p:dialog header="Create New Request" style="font-weight:bold"
widgetVar="requestNewDialog" resizable="false"
id="newDlg"
showEffect="fade" hideEffect="fade" appendToBody="true"
modal="true" position="center top" width="850" height="450">
<h:panelGrid columns="2" cellspacing="2">
<h:outputText value="New Employee No:" />
<h:outputText value="" />
</h:panelGrid>
<p:separator />
<p:panelGrid columns="6">
<h:outputLabel value="Employee # " for="emp" />
<p:autoComplete value="#
{myMB.selectedEmployee}"
id="basicPojo" minQueryLength="3"
completeMethod="#{myMB.complete}" var="p"
itemLabel="#{p.longName}"
converter="#{employeeNameConverter}"
forceSelection="true" >
<p:ajax event="itemSelect" update="num"
listener="#{myMB.handleSelect}" />
<h:outputLabel value="Name" for="name" />
<h:outputText value="#{p.employeeNumber}" />
</p:autoComplete>
<h:outputLabel id="num" value="Department" for="dept" />
<p:inputText id="dept" value="#{p.employeeNumber}" >
</p:inputText>
</p:panelGrid>
<p:separator />
</p:dialog>
ManagedBean complete Method
public List<Employee> complete(String query) {
List<Employee> suggestions;
suggestions = new ArrayList<Employee>();
try {
EmployeeQueryData q = new EmployeeQueryData ();
getService().getEmployee(q,query);
employee = q.getResult();
for (Employee p : employee) {
if (p.getEmpName().toLowerCase().contains(query));
suggestions.add(p); //
}
} catch (Exception e) {
}
return suggestions;
}
Use <p:ajax event="itemSelect"...
<p:autoComplete>...
<p:ajax event="itemSelect" update="someOtherFieldId someOtherFieldId2" />
</p:autoComplete>
I want to create h:datatable with list of data:
<h:dataTable id="dataTable" value="#{SessionsController.dataList}" binding="#{table}" var="item">
<!-- Check box -->
<h:column>
<f:facet name="header">
<h:outputText value="Select" />
</f:facet>
<h:selectBooleanCheckbox onclick="highlight(this)"
value="#{item.selected}" />
</h:column>
<h:column>
<f:facet name="header">
<h:commandLink value="№"
actionListener="#{SessionsController.sort}">
<f:attribute name="№" value="№" />
</h:commandLink>
</f:facet>
<h:outputText
value="#{table.rowIndex + SessionsController.firstRow + 1}" />
</h:column>
<h:column>
<f:facet name="header">
<h:commandLink value="Account Session ID"
actionListener="#{SessionsController.sort}">
<f:attribute name="sortField" value="Account Session ID" />
</h:commandLink>
</f:facet>
<h:outputText value="#{item.aSessionID}" />
</h:column>
<h:column>
<f:facet name="header">
<h:commandLink value="User ID"
actionListener="#{SessionsController.sort}">
<f:attribute name="sortField" value="User ID" />
</h:commandLink>
</f:facet>
<h:outputText value="#{item.userID}" />
</h:column>
<h:column>
<f:facet name="header">
<h:commandLink value="Activity Start Time"
actionListener="#{SessionsController.sort}">
<f:attribute name="sortField" value="Activity Start Time" />
</h:commandLink>
</f:facet>
<h:outputText value="#{item.activityStart}" />
</h:column>
<h:column>
<f:facet name="header">
<h:commandLink value="Activity End Time"
actionListener="#{SessionsController.sort}">
<f:attribute name="sortField" value="Activity End Time" />
</h:commandLink>
</f:facet>
<h:outputText value="#{item.activityEnd}" />
</h:column>
<h:column>
<f:facet name="header">
<h:commandLink value="Activity"
actionListener="#{SessionsController.sort}">
<f:attribute name="sortField" value="Activity" />
</h:commandLink>
</f:facet>
<h:outputText value="#{item.activity}" />
</h:column>
</h:dataTable>
I want when I click on a table row to open a new page which displays more details. I want to use the table key aSessionID which will be used for SQL query to get a data from the database. I know that I can use h:commandLink to pass the key but I don't want ugly html link. Is there other way to click on the JSF table row, pass a key and open a new window?
Best Wishes
EDIT
I found one possible solution here
Using this JavaScript code it's possible to open a new window when the user clicks on a row:
<table id="row_link">
<tbody>
<tr>
<td>link</td>
<td>info 1</td>
</tr>
<tr>
<td>link</td>
<td>info 2</td>
</tr>
</tbody>
</table>
$("table#row_link tbody tr").click(function () {
window.location = $(this).find("a:first").attr("href");
});
The question is how I can pass this key aSessionID to the new window.
In the above example href is used to pass the link to the new window. What attribute can be used in JSF table?
#BalusC (JSF expert) has a post about managing Datatable in JSF 1.2 but it works for JSF 2.x too. You're interested in the select row on click section.
UPDATE:
Let me explain the example. First, every JSF component ID will have this form: :, example:
<h:form id="myForm">
<h:inputText id="myInputText" value="#{myBean.textValue}" />
</h:form>
This will generate the HTML:
<form id="myForm">
<input type="text" id="myForm:myInputText" />
</form>
Second, you have to update the generated DOM for the datatable. He's doing that by javascript and also gives you the js code:
function addOnclickToDatatableRows() {
//gets all the generated rows in the html table
var trs = document.getElementById('form:dataTable').getElementsByTagName('tbody')[0]
.getElementsByTagName('tr');
//on every row, add onclick function (this is what you're looking for)
for (var i = 0; i < trs.length; i++) {
trs[i].onclick = new Function("highlightAndSelectRow(this)");
}
}
Third, define the highlightAndSelectRow js function (you can change the name to whatever you want).
function highlightAndSelectRow(tr) {
//get all the datatable rows
var trs = document.getElementById('form:dataTable').getElementsByTagName('tbody')[0]
.getElementsByTagName('tr');
//find the selected rowby using the tr parameter
for (var i = 0; i < trs.length; i++) {
if (trs[i] == tr) {
//once found it, change the color (maybe you don't need this part)
trs[i].bgColor = '#ff0000';
//update a hidden value in the form (maybe you need this code)
document.form.rowIndex.value = trs[i].rowIndex;
//here, you can add js code to open a new window
//or simulate a button/link click or something else you need.
} else {
trs[i].bgColor = '#ffffff';
}
}
}
UPDATE 2:
I've made a test for this case. I'll show you the code to get it done using facelets.
DataTable.xhtml
<script type="text/javascript">
function addOnclickToDatatableRows() {
//gets all the generated rows in the html table
var trs = document.getElementById('myForm:dataTable').getElementsByTagName('tbody')[0]
.getElementsByTagName('tr');
//on every row, add onclick function (this is what you're looking for)
for (var i = 0; trs.length > i; i++) {
trs[i].onclick = new Function("rowOnclick(this)");
}
}
function rowOnclick(tr) {
var elements = tr.cells[0].childNodes;
for(var i = 0; elements.length > i; i++) {
//get the link
if ((typeof elements[i].id !== "undefined") &&
(elements[i].id.indexOf("lnkHidden") > -1)) {
//open a new window/tab using the href generated in link
window.open(elements[i].href);
break;
}
}
return false;
}
</script>
<h:form id="myForm">
<h1>Show data</h1>
<h:dataTable id="dataTable" var="data" value="#{datatableBean.lstData}">
<h:column>
<f:facet name="header">
<h:outputText value="ID" />
</f:facet>
<h:outputText value="#{data.id}" />
<!-- define a hidden link for every row of the datatable
the value attribute contains the page to redirect. -->
<h:outputLink id="lnkHidden" value="AnotherPage.xhtml"
style="display:none">
<f:param name="id" value="#{data.id}" />
</h:outputLink>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Value" />
</f:facet>
<h:outputText value="#{data.value}" />
</h:column>
</h:dataTable>
</h:form>
DataTableBean class
#ManagedBean
#ViewScoped
public class DatatableBean {
private List<Data> lstData;
/**
* Creates a new instance of datatableBean
*/
public DatatableBean() {
lstData = new ArrayList<Data>();
lstData.add(new Data(1, "Hello World"));
lstData.add(new Data(2, "Hello StackOverflow"));
lstData.add(new Data(3, "Hello Luiggi"));
System.out.println("LOL");
}
//define getters and setters...
}
AnotherPage.xhtml
<h1>This is another page</h1>
<h:panelGrid columns="2">
<h:outputText value="Selected ID" />
<h:outputText value="#{anotherPageBean.id}" />
</h:panelGrid>
AnotherPageBean class
#ManagedBean
#RequestScoped
public class AnotherPageBean {
private int id;
/**
* Creates a new instance of AnotherPageBean
*/
public AnotherPageBean() {
try {
this.id = Integer.parseInt((String)FacesContext
.getCurrentInstance().getExternalContext()
.getRequestParameterMap().get("id"));
//by getting the id you can get more data
}
catch (Exception e) {
this.id = 0;
}
}