Reload a jsf datatable using jquery - jsf

my data table
<h:form>
<h:dataTable value="#{testController.items}" var="item" border="0">
<h:column>
<h:outputText value="#{item.name}"/>
</h:column>
</h:dataTable>
</h:form>
i'm using a modal to hold my form, the modal contains this commandbutton
<p:commandButton styleclass="btn btn-primary" action="#{testController.create}" oncomplete="handleComplete(xhr, status, args)" />
handleComplete function:
function handleComplete(xhr, status, args) {
if(args.validationFailed) {
alert("failed");
}else{
$('#test-modal').modal('hide');
// Do something here to reload the datatable to add the newly created item
}
}
im using jsf 2 and i also imported primefaces

You can use <p:remoteCommand> to generate a JavaScript function which invokes a JSF command action.
<h:form>
<h:dataTable id="table" value="#{testController.items}" var="item" border="0">
<h:column>
<h:outputText value="#{item.name}"/>
</h:column>
</h:dataTable>
<p:remoteCommand name="updateTable" action="#{testController.update}" update="table" />
</h:form>
This can be invoked as follows:
function handleComplete(xhr, status, args) {
if (args.validationFailed) {
alert("failed");
} else {
$('#test-modal').modal('hide');
updateTable();
}
}

Related

How to dynamically disable/enable commandbutton in datatable in JSF/PrimeFaces

I am displaying list of some objects in primefaces datatable. Apart from object related columns, I have added two columns that contain commandbutton. Each of these commandbutton make ajax calls to desired methods in bean. I want to disable both commandbuttons in that row when any of the button is clicked and enable them again once action is completed successfully. The method execution is simulated by ajaxStatus which is working fine.
Following is selected code of xhtml
<h:form id="form1" >
<p:remoteCommand name="onload" action="#{controlBean.init}" autoRun="true" />
<h:outputtext>Sample Project</h:outputtext>
<p:ajaxStatus style="display:block;margin-bottom:2em;height:24px;">
<f:facet name="prestart">
<h:outputText value="Starting..." /> </f:facet>
<f:facet name="error"> <h:outputText value="Error" />
</f:facet>
<f:facet name="success"> <h:outputText value="Success" />
</f:facet>
<f:facet name="default"> <h:outputText value="Idle" />
</f:facet>
<f:facet name="start"> <h:outputText value="Please Wait" />
<p:graphicImage name="/images/ajaxloadingbar.gif" />
</f:facet>
</p:ajaxStatus>
<p:dataTable var="appl" id="tbl1" rowIndexVar="rowIndx" value="#{controlBean.applsList}">
<p:column headerText="Name">
<h:outputText value="#{appl.applName}" />
</p:column>
<p:column headerText="Type">
<h:outputText value="#{appl.applType}" />
</p:column>
<p:column headerText="Desc" rendered="true">
<h:outputText value="#{appl.applDesc}" />
</p:column>
<p:column headerText="Start Appl" id="col4">
<p:commandButton value="Submit" ajax="true"
process="#this"
widgetVar="startButtonVar"
id="startBtn" update="msgs, col4, startBtn"
action="#{controlBean.startAction}" style="margin-right:20px;"
styleClass="ui-priority-primary"
disabled="#{controlBean.startBtnDisabled}">
<f:setPropertyActionListener value="#{appl}" target="#{controlBean.selectedAppl}"/>
</p:commandButton>
</p:column>
<p:column headerText="Stop Appl" id="col5">
<p:commandButton value="Submit" ajax="true"
process="#this"
widgetVar="stopButtonVar"
id="stopBtn" update="msgs, col5"
action="#{controlBean.stopAction}" style="margin-right:20px;"
styleClass="ui-priority-primary"
disabled="#{controlBean.btnDisabled}">
<f:setPropertyActionListener value="#{appl}" target="#{controlBean.selectedAppl}"/>
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
backing bean methods are as under:
public void startAction()
{
System.out.println("In start action method");
this.btnDisabled = true;
for(int i=0;i<100000;i++)
{
if(i%10000 == 0)
{
System.out.println(i);
}
for(int j=0;j<10000;j++)
{
for(int k=0;k<1000;k++)
{
}
}
}
MessageUtils.info(getSelectedAppl().getApplName()+" has been started");
this.btnDisabled = false;
}
public void stopAction()
{
System.out.println("In stop action method");
this.btnDisabled = true;
for(int i=0;i<100000;i++)
{
if(i%10000 == 0)
{
System.out.println(i);
}
for(int j=0;j<10000;j++)
{
for(int k=0;k<1000;k++)
{
}
}
}
MessageUtils.info(getSelectedAppl().getApplName()+" has been stopped");
this.btnDisabled = false;
}
Everything is working fine except disabling/enabling of commandbuttons. Any help in this regard will be highly appreciated.
Regards
You could disable them on the onclick javascript handler:
<p:commandButton id="startBtn"
widgetVar="startButtonVar"
onclick="PF('startButtonVar').disable();"
.....
The onclick will be executed BEFORE the AJAX call. On return, as the button is updated, it will be reenabled.

Using h:selectBooleanCheckbox to delete multiple rows in JSF datatable

I have followed the instruction as per the posts How to select multiple rows of <h:dataTable> with <h:selectBooleanCheckbox> and Using <h:selectBooleanCheckbox> with Map in a paginated <p:dataTable> throws NullPointerException
on how to delete multiple rows from a datatable. However, the checked Map object is not being populated with the the selected values. When I debug the application it is always empty.
Here is my code:
applicantSearch.xhtml
<ui:composition template="/WEB-INF/templates/main.xhtml">
<ui:define name="menu">
<ui:include src="/protected/views/menu.xhtml"/>
</ui:define>
<ui:define name="content">
<h:outputScript target="body">
formatMyTable();
</h:outputScript>
<h3>Search for Applicants</h3>
<h:form id="searchForm" class="form-search">
<h:panelGroup id="results" class="table-responsive">
<h:outputText id="informationMessage"
value="#{applicantSearchBacking.infoMessage}"
rendered="#{applicantSearchBacking.infoMessage ne null}"
class="informationMessage"/>
<div class="btn-toolbar">
<h:commandButton value="Delete Selected" onclick="if (! confirm('Are you sure you want to delete the selected applicants?')) return false" action="#{applicantSearchBacking.removeSelectedApplicants}" class="btn btn-danger btn-large pull-right">
<f:ajax render=":searchForm:results :searchForm:messages" onevent="formatMyTable"
/>
</h:commandButton>
</div>
<br/>
<h:dataTable value="#{applicantSearchBacking.applicantList}"
var="currentApplicant" styleClass="table table-hover table-condensed table-bordered"
>
<h:column>
<f:facet name="header">
Applicant ID
</f:facet>
#{currentApplicant.applicantId}
</h:column>
<h:column>
<f:facet name="header">
First Name
</f:facet>
#{currentApplicant.firstName}
</h:column>
<h:column>
<f:facet name="header">
Middle Name
</f:facet>
#{currentApplicant.middleName}
</h:column>
<h:column>
<f:facet name="header">
Last Name
</f:facet>
#{currentApplicant.lastName}
</h:column>
<h:column>
<f:facet name="header">
Actions
</f:facet>
<!-- User Access control section <c:if test=""> -->
<h:link value="Edit" outcome="#{applicantSearchBacking.editApplicant()}" class="btn btn-primary btn-sm">
<f:param name="myApplicantId" value="#{currentApplicant.applicantId}">
</f:param>
</h:link>
<!-- </c:if> -->
<!-- <c:if test=""> -->
<h:selectBooleanCheckbox id="del_checkbox" value="#{applicantSearchBacking.checked[currentApplicant.applicantId]}">
</h:selectBooleanCheckbox>
<!-- </c:if> -->
</h:column>
</h:dataTable>
</h:panelGroup>
<h:messages id="messages" class="errorMessage"/>
</h:form>
</ui:define>
applicantSearchBacking.java
private Map<Integer, Boolean> checked = new HashMap<>();
public void removeSelectedApplicants()
{
try {
List<Applicant> applicantsToDelete = new ArrayList<>();
for (Applicant applicant : applicantList) {
Boolean itemChecked = checked.get((applicant.getApplicantId()));
if (itemChecked !=null && itemChecked) {
applicantsToDelete.add(applicant);
}
}
applicantManager.removeSelectedApplicants(applicantsToDelete);
if (!checked.isEmpty())
infoMessage = "Applicant(s) deleted successfully";
checked.clear();
}
This construct will only work if exactly the same data model is preserved for the postback. So, if your bean is #RequestScoped, then it must be creating exactly the same applicantList inside #PostConstruct as it was when the form was displayed. Otherwise, you need to make the bean #ViewScoped. In any case, I assume that the getter method of applicantList doesn't do any business logic, but just solely returns the property.
See also:
Why JSF calls getters multiple times
How to choose the right bean scope?
commandButton/commandLink/ajax action/listener method not invoked or input value not updated - point 4
As per your question update, there's another potential mistake which may cause this construct to fail:
<f:ajax render=":searchForm:results :searchForm:messages" onevent="formatMyTable" />
The execute of <f:ajax> is here unspecified and uses then thus the default of #this. You need to explicitly specifiy #form in order to process the entire form on submit, otherwise only the parent component (the command button itself) would be processed.
<f:ajax execute="#form" ... />

render column in jsf datatable first time only

as per my requirement I have to show a delete button end of row in datattable but restriction is to show only for first row, not in each row.
how to restrict it
belwo is my datatable
<h:dataTable id="datatable" value="#{relationBean.languageDTOList}" var="lang">
<h:column>
<f:facet name="header"> Relation Type Name</f:facet>
<h:outputText value="#{relationBean.relationName}" />
</h:column>
<h:column>
<f:facet name="header"> Value</f:facet>
<h:inputText />
</h:column>
<h:column>
<f:facet name="header">language</f:facet>
<h:outputText value="#{lang.languageName}" />
</h:column>
<h:column>
<f:facet name="header"> Delete</f:facet>
<p:commandLink rendered="" action="#{relationBean.deleteDataTable}" immediate="true" update="#form" process="#this">
<h:graphicImage value="../images/delete.png" />
<f:setPropertyActionListener target="#{relationBean.deleteId}" value="#{var}" />
</p:commandLink>
</h:column>
Bean.java its showing contents of bean
public List<LanguageDTO> getLanguageDTOList() {
System.out.println("RelationBean:getLanguageDTOList:Enter");
CountryList = new ArrayList<Country>();
try {
CountryList.add(countryService.getCountryByCode(city));
List<LanguageDTO> tempLangDTOlst=new ArrayList<LanguageDTO>();
for (Country lang : CountryList) {
LanguageDTO languageDTO = new LanguageDTO();
for (CountryLanguage CLang : lang.getCountryLanguage()) {
languageDTO = new LanguageDTO();
languageDTO.setLanguageName(CLang.getLanguage().getLanguageName());
languageDTO.setLanguageCode(CLang.getLanguage().getLanguageCode());
System.out.println(CLang.getLanguage().getLanguageName());
tempLangDTOlst.add(languageDTO);
}
}
setLanguageDTOList(tempLangDTOlst);
System.out.println("languageDTOList :"+languageDTOList);
} catch (Exception e) {
e.printStackTrace();
}
//BeanUtils.copyProperties(tempLangDTO,languageDTOList);
System.out.println("--------------------Start -------------");
for (LanguageDTO iterable_element : languageDTOList) {
System.out.println(iterable_element.getLanguageName());
}
System.out.println("-------------------- End -------------");
System.out.println("RelationBean:getLanguageDTOList:Exit");
return languageDTOList;
}
Bind the <h:dataTable> to the view via binding, which will reference an UIData component instance and in the rendered attribute just check if UIData#getRowIndex() equals to 0.
<h:dataTable binding="#{table}" ...>
<h:column>
<p:commandLink ... rendered="#{table.rowIndex eq 0}">
(note: do not bind it to a bean like #{bean.table}! the code is complete as-is)
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?
JSF component binding without bean property
You can test if the current element is the same as the first element of your list:
<p:commandLink rendered="#{lang eq relationBean.languageDTOList.get(0)}"> ...
This would works only if languageDTOList is a List.
If you were using p:dataTable instead of the standard JSF DataTable, you could use the rowIndexVar variable to test if your are at the first iteration.

navigation when bean returns objects

Beginner question concerning changing the information in a view (and not going to a different .xhtml page). My .xhtml displays a datatable (which shows a list of people), but I want the user to be able to narrow the amount of info displayed by typing in the start of someones name into an inputtext and then clicking the commandbutton. Both the commandbutton and the datatable execute the same bean method, but if the inputtext has data the sql uses Like (this uses jdbc). My form is below, the problem is that I get an "Unable to find matching navigation case with from-view-id" because my managed bean returns a list of objects, not "success" or "failure". Also, the whole form seems inefficient. This seems like a fairly common scenario - calling managed bean's method that returns objects and not navigation instructions. How do I get rid of the error messages? Is there a better way to do this?
Here is code:
<h:head>
<h:outputStylesheet library="css" name="table-style.css" />
</h:head>
<h:body>
<h1>MavenWeb</h1>
<h:form>
<h:panelGrid columns="3">
Select a customer:
<h:inputText id="listName" value="#{customer.listName}"
size="20" >
</h:inputText>
<h:commandButton value="Submit"
action="#customer.getCustomerList()}" />
</h:panelGrid>
<h:dataTable value="#{customer.getCustomerList()}" var="c"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row"
>
<h:column>
<f:facet name="header">
Customer ID
</f:facet>
#{c.customerID}
</h:column>
<h:column>
<f:facet name="header">
Name
</f:facet>
#{c.name}
</h:column>
<h:column>
<f:facet name="header">
Address
</f:facet>
#{c.address}
</h:column>
<h:column>
<f:facet name="header">
Created Date
</f:facet>
#{c.created_date}
</h:column>
</h:dataTable>
</h:form>
</h:body>
First, make sure your managed bean has ViewScope, so only the form values will be affected on every request while you're in the same view. Second, you can add ajax behavior to your <h:commandButton> and render the <h:datatable> with the new values. Third, never put business logic inside your attribute getters, because the JSF framework could make 2 or more calls of those getters (depending on your design).
Using these rules, you can remake your code like this:
#ViewScoped
#ManagedBean
public class Customer {
private String listName;
private List<CustomerDTO> customerList;
public Customer() {
listName = "";
customerList = null; //maybe you can initialize your list here
}
//getters and setters...
//look that this method returns a void (no need to return a navigation rule)
public void fillCustomerList() {
//your method/way to fill the customerList goes here...
//I'll just put a code example
customerList = new ArrayList<CustomerDTO>();
customerList.add(new CustomerDTO(1, "Luiggi Mendoza", "Lima", new Date());
customerList.add(new CustomerDTO(2, "StackOverflow", "Web", new Date());
}
}
The code fragment for your page
<h:form>
<h:panelGrid columns="3">
Select a customer:
<h:inputText id="listName" value="#{customer.listName}" size="20" />
<h:commandButton value="Submit" action="#customer.fillCustomerList}">
<f:ajax execute="#this" render="dtMyDataTable" />
</h:commandButton>
</h:panelGrid>
<h:dataTable id="dtMyDataTable" value="#{customer.customerList}" var="c"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row">
<h:column>
<f:facet name="header">
Customer ID
</f:facet>
#{c.customerID}
</h:column>
<h:column>
<f:facet name="header">
Name
</f:facet>
#{c.name}
</h:column>
<h:column>
<f:facet name="header">
Address
</f:facet>
#{c.address}
</h:column>
<h:column>
<f:facet name="header">
Created Date
</f:facet>
#{c.created_date}
</h:column>
</h:dataTable>
</h:form>
More info on this matter:
Does view scope bean survive Navigation JSF
Learning JSF2: Ajax in JSF – using f:ajax tag

p:commandLink actionListener is processed for each row of p:dataTable while rendering the page

I have a dataTable that shows data stored in a database. One of the column contains a commandLink (p:commandLink) to edit selected row which is fine.
I have a problem during the rendering of my xhtml page. It seems that the method of backingBean in the actionListener attribute of commandLink is processed for every row in the table, but the actionListener should be processed only when link is clicked.
Here is my xhtml page (part of):
<h:form id="formElenco">
<p:dataTable id="dt1" value="#{myBean.itemList}" var="item">
<f:facet name="header">
<h:outputText value="header" />
</f:facet>
<p:column>
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{item.name}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="value" />
</f:facet>
<h:outputText value="#{item.value}"/>
</p:column>
<p:column>
<p:commandLink id="lnkItemUpdate" value="Edit"
onstart="document.getElementById('divUpdateItem').style.display = 'block';"
actionListener="#{myBean.updateItemAction(item)}" update=":formUpdateItem" />
</p:column>
</p:dataTable>
</h:form>
<div id="divUpdateItem" style="display:none" >
<h:form id="formUpdateItem">
Nome <h:inputText value="#{myBean.name}" /><br/>
Met <h:inputText value="#{myBean.value}" /><br/>
<h:inputHidden value="#{myBean.id}" />
<h:commandButton action="#{myBean.updateItemAction}" value="Save" />
</h:form>
</div>
Here are myBean's method (myBean is requestScoped):
public String updateItemAction(Entity item){
this.setId(item.getId());
this.setName(item.getName());
this.setValue(item.getValue());
return null;
}
public String updateItemAction() {
Entity entity = new Entity();
entity.setId(this.getId());
entity.setName(this.getName());
entity.setVAlue(this.getValue());
updateEntityQueryMethod(entity);
return null;
}
This isn't a valid method signature for an actionListener, so it's treated as a value expression by the <p:commandLink>.
You should be using action instead.
<p:commandLink id="lnkItemUpdate" value="Edit"
onstart="document.getElementById('divUpdateItem').style.display = 'block';"
action="#{myBean.updateItemAction(item)}" update=":formUpdateItem" />
Note that you can also just return void instead of a null String.
public void updateItemAction(Entity item) {
this.setId(item.getId());
this.setName(item.getName());
this.setValue(item.getValue());
}
A valid actionListener method signature would be a void method taking javax.faces.event.ActionEvent argument:
public void actionListener(ActionEvent event) {
// ...
}
See also:
Differences between action and actionListener

Resources