capture selected text from inputTextArea primefaces jsf - ajax

I want to capture selected text from inputTextArea on ajax dblclick or select event.How can I do this ?
The code below selects everything in the text area (which I don't want). Thank you very much.
<h:form id="form">
<p:panel header="Select Text">
<h:panelGrid columns="3" cellpadding="5">
<h:outputText value="Text: " />
<p:inputTextarea id="textarea"
value="#{selectedTextBean.selectedText}">
<p:ajax event="select" update="selectedText" />
</p:inputTextarea>
<h:outputText id="selectedText"
value="#{selectedTextBean.selectedText}" />
</h:panelGrid>
</p:panel>
</h:form>
Here is SelectedTextBean
#ManagedBean
#ViewScoped
public class SelectedTextBean {
public SelectedTextBean() {
}
private String selectedText;
public String getSelectedText() {
return selectedText;
}
public void setSelectedText(String selectedText) {
this.selectedText = selectedText;
}
}

You can use this plugin jquery-textrange.
xhtml
<p:inputTextarea onselect="setSelectedText()" />
<p:remoteCommand name="setSelectedTextCommand"
actionListener="#{mainBean.setSelectedText()}"
update="currentSelectedText" />
Selected Text is:
<h:outputText value="#{mainBean.selectedTextInArea}"
id="currentSelectedText" />
<h:outputScript library="js" name="jquery-textrange.js" />
<script>
function setSelectedText() {
var range = $('.ui-inputtextarea').textrange();// general selector
setSelectedTextCommand([{name: 'selectedText', value: range.text}]);
}
</script>
Bean
private String selectedTextInArea;
public void setSelectedText() {
FacesContext context = FacesContext.getCurrentInstance();
Map map = context.getExternalContext().getRequestParameterMap();
selectedTextInArea = (String) map.get("selectedText");
}
public String getSelectedTextInArea() {
return selectedTextInArea;
}
public void setSelectedTextInArea(String selectedTextInArea) {
this.selectedTextInArea = selectedTextInArea;
}
And Here's a live demo on Primefaces TextArea Selection, and on github.

You can do that sending a parameter to a remote command as follows:
The View
<h:form id="form">
<p:panel header="Select Text">
<h:panelGrid columns="3" cellpadding="5">
<h:outputText value="Text: " />
<h:panelGroup>
<p:inputTextarea id="textarea"
value="#{selectedTextBean.selectedText}" onselect="processSelection();" />
<p:remoteCommand name="sendSelection" actionListener="#{selectedTextBean.onSelect}" update="selectedText" process="#this" />
</h:panelGroup>
<h:outputText id="selectedText"
value="#{selectedTextBean.selectedText}" />
</h:panelGrid>
</p:panel>
</h:form>
<script>
function processSelection() {
var selectedText = (!!document.getSelection) ? document.getSelection() :
(!!window.getSelection) ? window.getSelection() :
document.selection.createRange().text;
sendSelection([{name: 'selectedText', value: selectedText}]);
}
</script>
Note that the text selection changes depending on the browser.
The Bean
import java.io.Serializable;
import java.util.Map;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
#ManagedBean
#ViewScoped
public class SelectedTextBean implements Serializable {
public SelectedTextBean() {
}
private String selectedText;
public void onSelect() {
FacesContext context = FacesContext.getCurrentInstance();
Map map = context.getExternalContext().getRequestParameterMap();
selectedText = (String) map.get("selectedText");
}
public String getSelectedText() {
return selectedText;
}
public void setSelectedText(String selectedText) {
this.selectedText = selectedText;
}
}

Related

Modal edit dialog on Primefaces with JSF

I'm trying to create some CRUD JSF application with edit/new screen implemented as a modal dialog. The problem is that I can't find a way how to make new and edit operation done by this dialog performed with ajax. With delete all was very simple (just ajax="true" option).
Here is a code of button which is used to show the dialog
<h:form id="dataForm">
<div class="ui-g">
<div class="ui-g-12 ui-md-9">
<p:dataGrid var="product" value="#{products.productList}" columns="3" layout="grid"
rows="12" paginator="true" id="products"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="6,12,16">
<f:event type="preRenderView" listener="#{products.preloadProductList}" />
<f:facet name="header">
Products
</f:facet>
<p:panel header="#{product.name}" style="text-align:center">
<h:panelGrid columns="1" style="width:100%">
<h:outputText value="#{product.name}"/>
<h:outputText value="#{product.price}"/>
<%-- Here new/edit dialog window is opened --%>
<p:commandLink update=":dataForm:productDetail" oncomplete="PF('productDialog').show()">
Edit
<f:setPropertyActionListener value="#{product}" target="#{products.product}"/>
</p:commandLink>
<p:commandLink update=":dataForm" action="#{products.deleteAction(product)}" ajax="true">
Delete
</p:commandLink>
</h:panelGrid>
</p:panel>
</p:dataGrid>
<ui:include src="WEB-INF/dialogs/edit_product.xhtml"/>
</div>
</div>
</h:form>
Here is dialog window which is moved to separete file edit_product.xhtml
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<p:dialog header="Product Info" widgetVar="productDialog" modal="true" showEffect="fade"
hideEffect="fade"
resizable="false">
<p:outputPanel id="productDetail" style="text-align:center;">
<p:panelGrid columns="2" rendered="#{not empty products.product}"
columnClasses="label,value">
<h:outputText value="Id:"/>
<h:outputText value="#{products.id}"/>
<h:outputText value="Name"/>
<h:inputText value="#{products.name}"/>
<h:outputText value="Price"/>
<h:inputText value="#{products.price}"/>
</p:panelGrid>
<h:commandButton value="Save" action="#{products.saveProduct}"/>
</p:outputPanel>
</p:dialog>
</ui:composition>
Here is Managed bean which is used by the Product dataGrid and dialog window.
#ManagedBean(name = "products")
#SessionScoped
public class ProductsBean {
private static final Logger logger = LoggerFactory.getLogger(ProductsBean.class);
#Inject
private ProductRepository productRepository;
private Product product;
private Collection<Product> productList;
public void preloadProductList(ComponentSystemEvent event) throws AbortProcessingException {
productList = productRepository.getAll();
}
public String getId() {
return String.valueOf(product.getId());
}
public void setId(String id) {
product.setId(Long.valueOf(id));
}
public String getName() {
return product.getName();
}
public void setName(String name) {
product.setName(name);
}
public int getPrice() {
return product.getPrice();
}
public void setPrice(int price) {
product.setPrice(price);
}
public Product getProduct() {
return this.product;
}
public void setProduct(Product product) {
this.product = product;
}
public Collection<Product> getProductList() {
logger.info("Get product list");
return productList;
}
public void newProductAction() {
this.product = new Product();
}
public void deleteAction(Product product) {
logger.info("Delete product");
productRepository.remove(product);
}
public void saveProduct() {
productRepository.merge(product);
}
}
No matter if I add ajax option or not the whole window is reloaded after Save button is pressed. Could you show me the right direction for the implementation, please?
P.S. If you need more code to answer you can find it here:
Main page with Product table https://github.com/usharik/GeekBrainsJavaEE/blob/master/lesson5-jpa/src/main/webapp/index.xhtml
Edit/New dialog https://github.com/usharik/GeekBrainsJavaEE/blob/master/lesson5-jpa/src/main/webapp/WEB-INF/dialogs/edit_product.xhtml

Ajax keyup event doesn't work after render

I have problem with JSF and Ajax. I used Ajax keyup event to filter selectOneListbox. It's working fine if I render all on start. When I hide panel with this component and render it when I select appropriate option in selectOneRadio, keyup event doesn't work.
JSF code:
<h:form id="form">
Client type: <h:selectOneRadio id="client_type" value="#{testBean.clientType}" styleClass="radio">
<f:selectItem itemValue="N" itemLabel="New client" />
<f:selectItem itemValue="E" itemLabel="Existing client" />
<f:ajax event="change" execute="#this" render="clientPanel" />
</h:selectOneRadio>
<br /><br />
<h:panelGroup id="clientPanel">
<h:panelGroup id="existedClient" rendered="#{testBean.clientType eq 'E'}">
<p style="font-weight: bold;">Existed client</p>
Search: <h:inputText id="in" value="#{testBean.clientSearchPattern}" autocomplete="off">
<f:ajax event="keyup" listener="#{testBean.clientChanged}" render="client_select" />
</h:inputText>
Client: <h:selectOneListbox id="client_select" value="#{testBean.complaint.client.id}" required="true"
style="width: 200px; font-family: 'Ubuntu'; font-size: 14.6667px; font-style: normal;">
<f:selectItems value="#{testBean.clients}" var="client"
itemLabel="#{client.name} #{client.surname}" itemValue="#{client.id}" />
</h:selectOneListbox>
</h:panelGroup>
<br /><br />
<h:panelGroup id="newClient" rendered="#{testBean.clientType eq 'N'}">
<p style="font-weight: bold;">New client</p>
Name: <h:inputText id="name" value="#{testBean.clientSearchPattern}" />
</h:panelGroup>
</h:panelGroup>
</h:form>
Java code:
#Named
#RequestScoped
public class TestBean {
#Inject
private ClientService clientService;
private String clientType = "N";
private String clientSearchPattern;
private List<Client> clients;
private Complaint complaint = new Complaint();
#PostConstruct
public void init() {
clients = clientService.list();
}
public void clientChanged() {
clients = clientService.search(clientSearchPattern);
}
public String getClientSearchPattern() {
return clientSearchPattern;
}
public void setClientSearchPattern(String clientSearchPattern) {
this.clientSearchPattern = clientSearchPattern;
}
public List<Client> getClients() {
return clients;
}
public Complaint getComplaint() {
return complaint;
}
public void setComplaint(Complaint complaint) {
this.complaint = complaint;
}
public String getClientType() {
return clientType;
}
public void setClientType(String clientType) {
this.clientType = clientType;
}
}
Thanks in advance!

Two ajax updates with h:selectOneMenu f:ajax

In short, if a component has been updated by Ajax, it can not launch new events Ajax
I have three h:selectOneMenu: A, B and C.
When I fire change event in A, then update the B h:selectOneMenu.
When I fire change event in B, then update the C h:selectOneMenu.
The problem is that when the content of B h:selectOneMenu is updated, the ajax in B don't work and C never can't be updated.
<h:selectOneMenu id="A" value="#{paqueteBean.mes}" label="a">
<f:selectItem itemLabel="Seleccione..." itemValue="" />
<f:selectItem itemLabel="Enero" itemValue="ENERO" />
<f:selectItem itemLabel="Febrero" itemValue="FEBRERO" />
<f:ajax listener="#{paqueteBean.changeMes}" render="B" />
</h:selectOneMenu>
<h:selectOneMenu id="B" value="#{paqueteBean.origen}" label="b">
<f:selectItem itemLabel="Seleccione..." itemValue="" />
<f:selectItems value="#{paqueteBean.origenes}" />
<f:ajax listener="#{paqueteBean.changeOrigen}" render="C"/>
</h:selectOneMenu>
<h:selectOneMenu id="C" value="#{paqueteBean.zona}" label="c">
<f:selectItem itemLabel="Seleccione..." itemValue="" />
<f:selectItems value="#{paqueteBean.zonas}" />
</h:selectOneMenu>
The ajax response is good, but simply don't work after the update:
<?xml version='1.0' encoding='UTF-8'?>
<partial-response id="j_id1"><changes><update id="B"><![CDATA[<select id="B" name="b" size="1" onchange="mojarra.ab(this,event,'valueChange','#this','C')"> <option value="">Seleccione...</option>
<option value="BUE">Ezeiza o Aeroparque</option>
</select>]]></update><update id="j_id1:javax.faces.ViewState:0"><![CDATA[-2984590031183218074:6198891110668113457]]></update></changes></partial-response>
UPDATE!
With PrimeFaces I have the same behavior:
<h:form id="filtro">
<p:selectOneMenu id="A" value="#{paqueteBean.mes}">
<f:selectItem itemLabel="Seleccione..." itemValue="" />
<f:selectItem itemLabel="Enero" itemValue="ENERO" />
<f:selectItem itemLabel="Febrero" itemValue="FEBRERO" />
<f:selectItem itemLabel="Marzo" itemValue="MARZO" />
<p:ajax listener="#{paqueteBean.changeMes}" update="B" />
</p:selectOneMenu>
<p:selectOneMenu id="B" value="#{paqueteBean.origen}"
disabled="#{empty paqueteBean.mes}">
<f:selectItem itemLabel="Seleccione..." itemValue="" />
<f:selectItems value="#{paqueteBean.origenes}" />
<p:ajax listener="#{paqueteBean.changeOrigen}" update="C"
process="origen mesSalida" />
</p:selectOneMenu>
<p:selectOneMenu id="C" value="#{paqueteBean.zona}"
disabled="#{empty paqueteBean.mes or empty paqueteBean.origen}">
<f:selectItem itemLabel="Seleccione..." itemValue="" />
<f:selectItems value="#{paqueteBean.zonas}" />
</p:selectOneMenu>
When I change some A values, the method in backing bean is fired, but when I change some B value, the method in backing bean is not fired.
The most strange is that for items that existed in B before the ajax update, the backing bean is called.
Backing Bean, nothing special:
public void changeMes(){
logger.debug("en changeMes el Mes es: " + this.mes);
this.origenes = new HashMap<String, String>();
this.origenes.put("Ezeiza o Aeroparque", "BUE");
}
public void changeOrigen(){
logger.debug("Mes: " + this.mes);
logger.debug("Origen" + this.origen);
this.zonas = new HashMap<String, String>();
this.zonas.put("Argentina", "AR");
this.zonas.put("Brasil", "BR");
}
public void changeZona(){
logger.debug("Mes: " + this.mes);
logger.debug("Origen" + this.origen);
logger.debug("Zona" + this.zona);
this.destinos = new HashMap<>();
this.destinos.put("Mar del Plata", "MDQ");
this.destinos.put("Punta Lara", "LTA");
}
UPDATE:
here is a working example:
Bean:
import java.util.ArrayList;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.model.SelectItem;
#ManagedBean(name="myBean")
#SessionScoped
public class MyBean {
private boolean bDisabled;
private boolean cDisabled;
private String selectedA;
private String selectedB;
private String selectedC;
private ArrayList<SelectItem> aItems;
private ArrayList<SelectItem> bItems;
private ArrayList<SelectItem> cItems;
public MyBean() {
}
#PostConstruct
public void init(){
try{
this.bDisabled = new Boolean(true);
this.cDisabled = new Boolean(true);
this.aItems = new ArrayList<SelectItem>();
this.bItems = new ArrayList<SelectItem>();
this.cItems = new ArrayList<SelectItem>();
this.aItems.add(new SelectItem("NONE", "---?"));
this.aItems.add(new SelectItem("A1", "A 1"));
this.aItems.add(new SelectItem("A1", "A 1"));
this.aItems.add(new SelectItem("A1", "A 1"));
this.bItems.add(new SelectItem("NONE", "---?"));
this.cItems.add(new SelectItem("NONE", "---?"));
}catch(Exception e){
e.printStackTrace();
}
}
public final void selectA(final AjaxBehaviorEvent event){
try{
System.out.println(this.selectedA);
this.bItems.clear();
this.bItems.add(new SelectItem("NONE", "---?"));
if(this.selectedA.equals("NONE") ){
this.setbDisabled(true);
return;
}
this.bItems.add(new SelectItem("B1","B 1"));
this.setbDisabled(false);
}catch(Exception ex){
ex.printStackTrace();
}
}
public final void selectB(final AjaxBehaviorEvent event){
try{
System.out.println(this.selectedB);
this.cItems.clear();
this.cItems.add(new SelectItem("NONE", "---?"));
if(this.selectedB.equals("NONE") ){
this.setcDisabled(true);
return;
}
this.cItems.add(new SelectItem("C1","C 1"));
this.setcDisabled(false);
}catch(Exception ex){
ex.printStackTrace();
}
}
public final void selectC(final AjaxBehaviorEvent event){
try{
System.out.println(this.selectedC);
}catch(Exception ex){
ex.printStackTrace();
}
}
public String getSelectedA() {
return selectedA;
}
public void setSelectedA(String selectedA) {
this.selectedA = selectedA;
}
public String getSelectedB() {
return selectedB;
}
public void setSelectedB(String selectedB) {
this.selectedB = selectedB;
}
public String getSelectedC() {
return selectedC;
}
public void setSelectedC(String selectedC) {
this.selectedC = selectedC;
}
public ArrayList<SelectItem> getaItems() {
return aItems;
}
public void setaItems(ArrayList<SelectItem> aItems) {
this.aItems = aItems;
}
public ArrayList<SelectItem> getbItems() {
return bItems;
}
public void setbItems(ArrayList<SelectItem> bItems) {
this.bItems = bItems;
}
public ArrayList<SelectItem> getcItems() {
return cItems;
}
public void setcItems(ArrayList<SelectItem> cItems) {
this.cItems = cItems;
}
public boolean isbDisabled() {
return bDisabled;
}
public void setbDisabled(boolean bDisabled) {
this.bDisabled = bDisabled;
}
public boolean iscDisabled() {
return cDisabled;
}
public void setcDisabled(boolean cDisabled) {
this.cDisabled = cDisabled;
}
}
XHTML:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
<h:head>
<meta charset="UTF-8" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>Test</title>
</h:head>
<body>
<f:view>
<h:form id="dataForm">
<h:selectOneMenu value="#{myBean.selectedA}" style="width: 100%;">
<f:selectItems value="#{myBean.aItems}" />
<f:ajax execute="#form" render="#form" listener="#{myBean.selectA}" />
</h:selectOneMenu>
<h:selectOneMenu disabled="#{myBean.bDisabled}" value="#{myBean.selectedB}" style="width: 100%;">
<f:selectItems value="#{myBean.bItems}" />
<f:ajax execute="#form" render="#form" listener="#{myBean.selectB}" />
</h:selectOneMenu>
<h:selectOneMenu disabled="#{myBean.cDisabled}" value="#{myBean.selectedC}" style="width: 100%;">
<f:selectItems value="#{myBean.cItems}" />
<f:ajax execute="#form" render="#form" listener="#{myBean.selectC}" />
</h:selectOneMenu>
</h:form>
</f:view>
</body>
</html>
Instead of using <f:ajax/> you can also use the PrimeFaces-Ajax-Element <p:ajax> which offers you a update-attribute:
<p:ajax update="elementID"/>
Another possibility I can recommend: Have you tried to put your SelectOneMenus in a <h:form>-Element? It looks like you didn't use a form. Do so, then you can always update the form in order to make the menues change. Worked good for me at my projects.
I had the same mistake.
For the second selectonemenu i miss a setter.
In your code it was the setter for myBean.selectedB.
Check all your getter and setter. Maybe there is the problem

PrimeFaces PropertyNotFoundException Target Unreachable, 'null' returned null

I am having problems with the site I am creating. I am new to Faces 2.0 and was only using JSP and now shifting to Faces 2.0. I have a page that adds and deletes a location Zip Code. The edit part works but the add part, I am having an error:
PropertyNotFoundException, Target Unreachable, 'null' returned null.
on following value:
value="#{zipCodeMaintennanceBean.selectedZipCode.description}"
I dont know why it does not work because the edit part works and they use the same ManagedBean.
I am using Spring 3.1.3 With Hibernate and PrimeFaces 3.5. I hope someone answers my question as I dont know how to solve this.
I suspect that whenever I click the button, a new object is being created as I am using a #RequestScoped annotation.
I tried to from instantiating the entity class on #PostConstruct Method, even instantiating the entity on the declaration and setting an empty string on description and nothing works.
It doesnt get to call save() method and seems to get stuck on the Update Model Values Phase
Below is my xhtml page:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<ui:composition template="/WEB-INF/views/template.xhtml">
<ui:define name="content">
<table border="0" width="100%">
<tr align="center">
<td><c:if test="${not empty param.login_error}">
<div class="error"
style="font-family: serif; font-size: medium; color: red;">
#{msg['label.login.invalidlogon']}<br />
#{sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}
</div>
</c:if> <c:if test="">
<div class="message"
style="font-family: serif; font-size: medium; color: red;">
${sessionScope.messageVariable}</div>
</c:if> </td>
</tr>
</table>
<p:panelGrid columns="3">
<h:form id="form">
<f:facet name="header">
<p:row>
<p:column colspan="3">#{msg['usrmnt.header']}</p:column>
</p:row>
</f:facet>
<p:row>
<p:column>
<h:outputLabel for="userSearch" value="Search ZipCode/Description" />
</p:column>
<p:column>
<p:inputText styleClass="new-fld" id="userSearch"
value="#{zipCodeMaintennanceBean.searchString}">
</p:inputText>
</p:column>
<p:column>
<p:commandButton value="#{msg['usrmnt.searchbutton']}"
actionListener="#{zipCodeMaintennanceBean.search}"
update="panel,dataTable" process="#form" />
<p:commandButton value="Add"
actionListener="#{zipCodeMaintennanceBean.triggerAdd}"
update="panel,:#{p:component('displayadd')}"
oncomplete="addDialog.show()" />
</p:column>
</p:row>
<p:row>
<p:column colspan="3" styleClass="ui-widget-header">
<p:spacer height="0" />
</p:column>
</p:row>
<p:row>
<p:column colspan="3">
<p:outputPanel id="panel">
<p:dataTable id="dataTable" var="zip"
value="#{zipCodeMaintennanceBean.zipCodes}" paginator="true"
rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15"
rendered="#{zipCodeMaintennanceBean.hasSearchResult}"
selectionMode="single"
selection="#{zipCodeMaintennanceBean.selectedZipCode}"
rowKey="#{zip.zipcode}">
<p:ajax event="rowSelect"
listener="#{zipCodeMaintennanceBean.onRowSelect}"
oncomplete="editDialog.show()"
update=":#{p:component('display')}" />
<p:ajax event="rowUnselect"
listener="#{zipCodeMaintennanceBean.onRowUnselect}" />
<f:facet name="header">
Users
</f:facet>
<p:column>
<f:facet name="header">
<h:outputText value="Zip Code" />
</f:facet>
<h:outputText value="#{zip.zipcode}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Description" />
</f:facet>
<h:outputText value="#{zip.description}" />
</p:column>
</p:dataTable>
</p:outputPanel>
</p:column>
</p:row>
<p:dialog header="Add ZipCode" widgetVar="addDialog" id="addDialog"
modal="true" showEffect="clip" hideEffect="fold" dynamic="true">
<p:outputPanel autoUpdate="true">
<p:panelGrid cellpadding="4" id="displayadd"
rendered="#{zipCodeMaintennanceBean.addMode}"
styleClass="maintennancePanelGrid">
<f:facet name="header">
<p:row>
<p:column colspan="3">
<h:outputText value="Add Zip Code" />
</p:column>
</p:row>
</f:facet>
<p:row>
<p:column>
<h:outputLabel for="zipcodeAdd" value="Zip Code:" />
</p:column>
<p:column>
<p:inputText styleClass="new-fld" id="zipcodeAdd"
value="#{zipCodeMaintennanceBean.selectedZipCode.zipcode}"
label="Zip Code" required="true">
<f:validateLength for="userName" minimum="4" maximum="6"></f:validateLength>
</p:inputText>
</p:column>
<p:column>
<p:message for="zipcodeAdd"></p:message>
</p:column>
</p:row>
<p:row>
<p:column>
<h:outputLabel for="descriptionAdd" value="Description: " />
</p:column>
<p:column>
<p:inputText styleClass="new-fld" id="descriptionAdd"
required="true"
value="#{zipCodeMaintennanceBean.selectedZipCode.description}"
label="Description"></p:inputText>
</p:column>
<p:column>
<p:message for="descriptionAdd"></p:message>
</p:column>
</p:row>
<f:facet name="footer">
<p:row>
<p:column styleClass="text-align:center" colspan="3">
<p:commandButton value="Submit"
update=":#{p:component('displayadd')}"
action="#{zipCodeMaintennanceBean.add}"
oncomplete="if (!args.validationFailed) addDialog.hide()" process="#form" />
</p:column>
</p:row>
<p:row>
<p:column colspan="3">
</p:column>
</p:row>
</f:facet>
</p:panelGrid>
</p:outputPanel>
</p:dialog>
<p:dialog header="Edit ZipCode" resizable="false" id="editDialog"
widgetVar="editDialog" modal="true" showEffect="clip"
hideEffect="fold" closeOnEscape="true" dynamic="true">
<p:outputPanel autoUpdate="true">
<p:panelGrid cellpadding="4" id="display"
rendered="#{zipCodeMaintennanceBean.hasSelectedZipCode}"
styleClass="maintennancePanelGrid">
<f:facet name="header">
<p:row>
<p:column colspan="3">
<h:outputText value="Edit Zip Code" />
</p:column>
</p:row>
</f:facet>
<p:row>
<p:column>
<h:outputLabel for="zipcode" value="Zip Code:" />
</p:column>
<p:column>
<p:inputText styleClass="new-fld" id="zipcode"
value="#{zipCodeMaintennanceBean.selectedZipCode.zipcode}"
label="Zip Code" disabled="true">
<f:validateLength for="userName" minimum="4" maximum="6"></f:validateLength>
</p:inputText>
</p:column>
<p:column>
<p:message for="zipcode"></p:message>
</p:column>
</p:row>
<p:row>
<p:column>
<h:outputLabel for="descripton" value="Description: " />
</p:column>
<p:column>
<p:inputText styleClass="new-fld" id="description"
required="true"
value="#{zipCodeMaintennanceBean.selectedZipCode.description}"
label="Description"></p:inputText>
</p:column>
<p:column>
<p:message for="description"></p:message>
</p:column>
</p:row>
<f:facet name="footer">
<p:row>
<p:column styleClass="text-align:center" colspan="3">
<p:commandButton value="Submit"
update="panel,:#{p:component('display')}"
action="#{zipCodeMaintennanceBean.save}"
oncomplete="if (!args.validationFailed) editDialog.hide()" />
<p:commandButton value="Delete"
update="panel,:#{p:component('display')}"
action="#{zipCodeMaintennanceBean.delete}"
oncomplete="if (!args.validationFailed) editDialog.hide()"
process="#this">
</p:commandButton>
<p:confirmDialog global="true" showEffect="fade"
hideEffect="explode">
<p:commandButton value="Yes" type="button"
styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
<p:commandButton value="No" type="button"
styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
</p:confirmDialog>
</p:column>
</p:row>
<p:row>
<p:column colspan="3">
</p:column>
</p:row>
</f:facet>
</p:panelGrid>
</p:outputPanel>
</p:dialog>
</h:form>
</p:panelGrid>
</ui:define>
</ui:composition>
</html>
Below is my Backing Bean:
package com.siteam.web.bean;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.UnselectEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import com.siteam.web.invsys.dao.ZipCodeDao;
import com.siteam.web.invsys.entities.TblZipcodes;
#ManagedBean(name = "zipCodeMaintennanceBean")
#RequestScoped
#Service
public class ZipCodeMaintennanceBean {
private TblZipcodes selectedZipCode = new TblZipcodes();
private boolean hasSelectedZipCode = false;
private List<TblZipcodes> zipCodes = new ArrayList<TblZipcodes>();
private ZipCodeDao zipCodeDao;
private boolean hasSearchResult = false;
private String searchString;
private boolean addMode;
public void triggerAdd() {
init();
this.addMode = true;
}
public String add() {
try {
this.selectedZipCode.setDateupdated(Calendar.getInstance()
.getTime());
this.zipCodeDao.add(this.selectedZipCode);
this.zipCodeDao.refresh(this.selectedZipCode);
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_INFO, "Zip Code Saved. ",
"Saved Zip Code"));
context.getExternalContext().getFlash().setKeepMessages(true);
init();
this.addMode = false;
return "zipmnt";
} catch (DataIntegrityViolationException ex) {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_WARN, "Error:",
"ZipCode Already Exists"));
ex.printStackTrace();
return "";
} catch (NullPointerException npe) {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_ERROR, "Error:", npe.getMessage()));
npe.printStackTrace();
return "";
} catch (Throwable th) {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_ERROR, "Error:", th.getCause()
.getMessage()));
th.printStackTrace();
return "";
}
}
public String save() {
try {
this.selectedZipCode.setDateupdated(Calendar.getInstance()
.getTime());
this.zipCodeDao.update(this.selectedZipCode);
this.zipCodeDao.refresh(this.selectedZipCode);
FacesContext context = FacesContext.getCurrentInstance();
init();
// RequestContext.getCurrentInstance().execute("editDialog.hide()");
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_INFO, "Zip Code Saved. ",
"Saved Zip Code"));
context.getExternalContext().getFlash().setKeepMessages(true);
hasSearchResult = false;
this.hasSelectedZipCode = false;
return "zipmnt";
} catch (DataIntegrityViolationException ex) {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_WARN, "Error:",
"ZipCode Already Exists"));
ex.printStackTrace();
return "";
} catch (NullPointerException npe) {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_ERROR, "Error:", npe.getMessage()));
npe.printStackTrace();
return "";
} catch (Throwable th) {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_ERROR, "Error:", th.getCause()
.getMessage()));
th.printStackTrace();
return "";
}
}
public String delete() {
try {
this.zipCodeDao.delete(this.selectedZipCode);
FacesContext context = FacesContext.getCurrentInstance();
init();
// RequestContext.getCurrentInstance().execute("editDialog.hide()");
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_INFO, "Zip Code Deleted. ",
"Deleted Zip Code"));
context.getExternalContext().getFlash().setKeepMessages(true);
hasSearchResult = false;
this.hasSelectedZipCode = false;
return "zipmnt";
} catch (DataIntegrityViolationException ex) {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_WARN, "Error:",
"ZipCode Already Exists"));
ex.printStackTrace();
return "";
} catch (NullPointerException npe) {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_ERROR, "Error:", npe.getMessage()));
npe.printStackTrace();
return "";
} catch (Throwable th) {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_ERROR, "Error:", th.getCause()
.getMessage()));
th.printStackTrace();
return "";
}
}
#PostConstruct
public void init() {
this.hasSelectedZipCode = false;
this.hasSearchResult = false;
this.addMode = false;
this.selectedZipCode = new TblZipcodes();
this.selectedZipCode.setDescription("");
this.zipCodes.clear();
}
public void search() {
hasSearchResult = false;
TblZipcodes zipCode = new TblZipcodes();
zipCode.setZipcode(searchString);
this.zipCodes = zipCodeDao.findZipCodes(zipCode);
if (zipCodes.size() > 0) {
hasSearchResult = true;
}
}
public TblZipcodes getSelectedZipCode() {
return selectedZipCode;
}
public void setSelectedZipCode(TblZipcodes selectedZipCode) {
this.selectedZipCode = selectedZipCode;
}
public boolean isHasSelectedZipCode() {
return hasSelectedZipCode;
}
public void setHasSelectedZipCode(boolean hasSelectedZipCode) {
this.hasSelectedZipCode = hasSelectedZipCode;
}
public List<TblZipcodes> getZipCodes() {
return zipCodes;
}
public void setZipCodes(List<TblZipcodes> zipCodes) {
this.zipCodes = zipCodes;
}
public ZipCodeDao getZipCodeDao() {
return zipCodeDao;
}
#Autowired
public void setZipCodeDao(ZipCodeDao zipCodeDao) {
this.zipCodeDao = zipCodeDao;
}
public boolean isHasSearchResult() {
return hasSearchResult;
}
public void setHasSearchResult(boolean hasSearchResult) {
this.hasSearchResult = hasSearchResult;
}
public String getSearchString() {
return searchString;
}
public void setSearchString(String searchString) {
this.searchString = searchString;
}
public void onRowSelect(SelectEvent event) {
this.selectedZipCode = (TblZipcodes) event.getObject();
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
"Selected Zip Code", "Zip Code Selected: "
+ selectedZipCode.getZipcode());
zipCodeDao.refresh(this.selectedZipCode);
FacesContext.getCurrentInstance().addMessage(null, msg);
this.hasSelectedZipCode = true;
}
public void onRowUnselect(UnselectEvent event) {
// FacesMessage msg = new FacesMessage("Car Unselected", ((Car)
// event.getObject()).getModel());
this.selectedZipCode = new TblZipcodes();
this.hasSelectedZipCode = false;
}
public boolean isAddMode() {
return addMode;
}
public void setAddMode(boolean addMode) {
this.addMode = addMode;
}
}
Below is my Zip Code Entity Code
package com.siteam.web.invsys.entities;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
#Entity
#Table(name = "TBL_ZIPCODES", schema = "INVSYS")
public class TblZipcodes implements java.io.Serializable {
private String zipcode;
private String description = "";
private Date dateupdated;
private Set<TblCustomer> tblCustomers = new HashSet<TblCustomer>(0);
public TblZipcodes() {
}
public TblZipcodes(String zipcode) {
this.zipcode = zipcode;
}
public TblZipcodes(String zipcode, String description, Date dateupdated,
Set tblCustomers) {
this.zipcode = zipcode;
this.description = description;
this.dateupdated = dateupdated;
this.tblCustomers = tblCustomers;
}
#Id
#Column(name = "ZIPCODE", unique = true, nullable = false, length = 5)
public String getZipcode() {
return this.zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
#Column(name = "DESCRIPTION", length = 50)
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
#Temporal(TemporalType.DATE)
#Column(name = "DATEUPDATED", length = 7)
public Date getDateupdated() {
return this.dateupdated;
}
public void setDateupdated(Date dateupdated) {
this.dateupdated = dateupdated;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "tblZipcodes")
public Set<TblCustomer> getTblCustomers() {
return this.tblCustomers;
}
public void setTblCustomers(Set<TblCustomer> tblCustomers) {
this.tblCustomers = tblCustomers;
}
#Override
public boolean equals(Object newObject) {
return newObject instanceof TblZipcodes;
}
// This must return the same hashcode for every Foo object with the same key.
public int hashCode() {
return this.getClass().hashCode();
}
}
Thank you in advance.
In your dataTable you are using the same variable for row selection.
selectionMode="single" selection="#{zipCodeMaintennanceBean.selectedZipCode}"
When no row is selected the selectedZipCode attribute will be null and you will continue to get an Exception.
You could simply use another instance of TblZipcodes for the addDialog.
PS: Some time ago someone reported a bug when giving the same name to id and widgetVar as you did in addDialog, check if this is a problem in version 3.5.

JSF 2.0 AJAX: jsf.ajax.request to call method not only rerender an area of page

I'm looking for a soultion of the following problem:
_The is a list of links with different types of cars.
_The user can click on each car in the list and a ajax request should be sent.
_The response of the ajax request should be dependent on the id (of each car) and displayed in an panelGroup.
So what I need is a possibility to call a method on the backing-bean. Additionally, this method should be called with a car id as its parameter.
My code so far looks like:
...
function showDetails(detailsFor){
jsf.ajax.request(this, event, {render: 'form1:carDetails'});
}
...
<ul>
<ui:repeat value="#{carTree.getCars)}" var="car">
<h:outputScript name="jsf.js" library="javax.faces" target="head" />
<li onclick="showDetails(#{car.id});">#{car.name}</li>
</ui:repeat>
</ul>
...
<h:panelGroup id="carDetails" layout="block" style="float:left;">
// need the details of each 'selected /clicked' car here
</h:panelGroup>
...
And the method in the backing bean should look like:
public class CarTree {
...
public String getCarDetails(int carid){
return "The car details for the car id "+carid+" are......";
}
...
}
I've no idea how to call a method by using the new JSF 2.0 AJAX functionality. Please, help me...
Use f:setPropertyActionListener to pass a object from JSF page to your backend. This tag is especially useful when you are using repeatable components like datatable
No need to use raw JavaScript, you can use <f:ajax />. Plus instead of worrying about Car id and all, just send it completely to backing bean.
Here is a sample example:
The Car class:
public class Car {
int id;
String brand;
String color;
public Car(int id, String brand, String color) {
this.id = id;
this.brand = brand;
this.color = color;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
}
The CarTree class:
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean(name = "CarTree")
#RequestScoped
public class CarTree {
List<Car> carList;
Car selectedCar;
public Car getSelectedCar() {
return selectedCar;
}
public void setSelectedCar(Car selectedCar) {
this.selectedCar = selectedCar;
}
public List<Car> getCars() {
return carList;
}
public void setCars(List<Car> carList) {
this.carList = carList;
}
public CarTree() {
carList = new ArrayList<Car>();
carList.add(new Car(1, "jaguar", "grey"));
carList.add(new Car(2, "ferari", "red"));
carList.add(new Car(3, "camri", "steel"));
}
}
The JSF page:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body id="mainBody">
<h:form id="carForm">
<h:dataTable value="#{CarTree.cars}" var="car">
<h:column>
<h:outputText value="#{car.id}"/>
</h:column>
<h:column>
<h:outputText value="#{car.brand}"/>
</h:column>
<h:column>
<h:outputText value="#{car.color}"/>
</h:column>
<h:column>
<h:commandButton value="Show Car Detail" >
<f:setPropertyActionListener target="#{CarTree.selectedCar}" value="#{car}"/>
<f:ajax render=":carForm:carDetails" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:panelGroup id="carDetails" layout="block" style="float:left;">
<h:outputText value="#{CarTree.selectedCar.id}" />
<h:outputText value="#{CarTree.selectedCar.brand}" />
<h:outputText value="#{CarTree.selectedCar.color}" />
</h:panelGroup>
</h:form>
</h:body>
</html>
Hope this helps.
I haven't tested myself, but I'd suggest you try something like this (assuming your class CarTree is #Named and, therefore, can be referred to inside the JSF page using the name carTree):
<ul>
<ui:repeat value="#{carTree.getCars)}" var="car">
<li><h:commandLink action="#{carTree.getCarDetails(car.id)}" value="#{car.name}">
<f:ajax render="carDetails" />
</h:commandLink></li>
</ui:repeat>
</ul>
...
<h:panelGroup id="carDetails" layout="block" style="float:left;">
// need the details of each 'selected /clicked' car here
</h:panelGroup>
I think the contents of the action property in the <h:commandLink /> can also be coded as the listener property in the <f:ajax /> tag. Don't know if there's any difference...
If you don't want to use <h:commandLink /> you could replace it with <h:outputText /> and add the property event="click" to the <f:ajax /> tag. I think that would work as well. In this case, the method call would have to be in the listener property of the <f:ajax /> tag.

Resources