JSF Primefaces: Update a dataTable open in another tab? - jsf-2.2

I have a simple webapp which allows the user to create transactions, and on another page the user can see all past transactions. I would like:
To have the dataTable be up-to-date when I open the past transaction page
To update the dataTable when I create a transaction on the creation page
I am not sure if this can be covered by one or two functionalities. Also, I am not sure how to decouple the functionalities. Should the creation of a transaction trigger the refresh of the dataTable, or should the dataTable itself find new entries in the DB ?
The past transactions page:
My TransactionListModel
package model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import entity.Transaction;
#Named
#SessionScoped
public class TransactionListModel implements Serializable {
private static final long serialVersionUID = 1L;
private List<Transaction> txList;
#PostConstruct
public void init() {
txList = new ArrayList<Transaction>();
}
public List<Transaction> getTxList() {
return txList;
}
public void clearList(){
txList = new ArrayList<Transaction>();
}
}
My Transaction view
<!-- Fill the table before rendering -->
<f:event type="preRenderView" listener="# {transactionListController.findAllTx()}" />
<h:form id="alltxform">
<p:dataTable id="tableAllTransactions" var="transaction"
value="#{transactionListModel.txList}">
<f:facet name="header">Transactions</f:facet>
<p:column headerText="Id">
<h:outputText value="#{transaction.id}" />
</p:column>
</p:dataTable>
</h:form>
My TransactionList Controller
#Named
#RequestScoped
public class TransactionListController implements Serializable {
private static final long serialVersionUID = 1L;
#Inject
private Logger log;
#Inject
private TransactionService txService;
#Inject
private TransactionListModel txListModel;
public void findAllTx() {
txListModel.clearList();
txListModel.getTxList().addAll(txService.findAllTx());
}
public void reset() {
if (txListModel.getTxList() != null) {
txListModel.clearList();
}
}
}
The creation page
There is a simple textInputField (bound to a model) with a button:
<h:commandButton id="sendtx" value="Send" styleClass="ui-priority-primary">
<f:actionListener binding="#{transactionXmlController.sendTx()}" />
</h:commandButton>
The called method:
public void sendTx() {
FacesMessage message;
if (!transactionService.sendTx(transactionXmlEditableModel.getXml()).equals("OK"))
message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "KO");
else {
message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Success", "OK");
}
fc.addMessage(null, message);
}
So far, this works.
My Questions
How do I reload the dataTable with AJAX ?
I would like the dataTable to update even if it has been opened in another tab before the creation of a new transaction. How to do this ?
How to replace my "f:event type="preRenderView" with a viewAction in order to fill the dataTable before rendering the page ?

I'm not sure how you would update the table in another tab, without something like <p:poll> but to update your table with Ajax you can do something like:
<h:commandButton id="sendtx" value="Send" styleClass="ui-priority-primary">
<f:ajax listener = '#{transactionXmlController.sendTx()}' render="alltxform:tableAllTransactions" />
</h:commandButton>

Related

ui repeat to show one more value and method is not invoking in managed Bean in JSF2.2

<ui:repeat value="#{cc.attrs.bean.foo.foo1}" var="test" varStatus="test1">
<h:outputText value="#{test.prime}" title="#{test.primeNumber}" />
<h:outputText value="," rendered="#{!test1.last}" />
</ui:repeat>
I am getting a value example1,example2
Now after adding a new line:
<ui:repeat value="#{cc.attrs.bean.foo.foo1}" var="test" varStatus="test1">
<h:outputText value="#{cc.attrs.bean.testNo(test)}" rendered="#{test1.first}" />
<h:outputText value="#{test.prime}" title="#{test.primeNumber}" />
<h:outputText value="," rendered="#{!test1.last}" />
</ui:repeat>
I want my output something like this Hello- example1,example2......
But I am not able to get this output. In fact testNo(test) method is not invoked. What exactly is getting wrong over here. Thank you in advance
Manage bean method
private String testNo(Test test) {
List<Test11> type = Lists.newArrayList();
String some = someService.findTestNumber(test.getSomeNumber());
return some;
}
You need to make a basic MVC webapp. There are many tutorials about this, but example always helps: Your model is simple, two entities for a CompletedTest:
#Entity
public class CompletedTest {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
#OneToMany(fetch=FetchType.EAGER)
private List<TestResult> results;
// getters and setters
}
and a TestResult:
#Entity
public class TestResult {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String result;
// constructors, getters, setters
}
Access your model through a service layer
#Stateless
public class TestService {
#Inject
private EntityManager em;
public CompletedTest findTestResultByName(String name) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<CompletedTest> q = cb.createQuery(CompletedTest.class);
Root<CompletedTest> tr = q.from(CompletedTest.class);
q.select(tr).where(cb.equal(tr.get("name"), name));
List<CompletedTest> testResults = em.createQuery(q).getResultList();
if ( testResults.size() > 0 ) return testResults.get(0);
else return null;
}
The create a controller to interface to your view:
#Model
public class TestResultController {
#Inject
private TestService testResultService;
private CompletedTest testResult;
#PostConstruct
public void init() {
testResult = testResultService.findTestResultByName("Test #1");
}
and finally your view is your JSF page:
<ui:repeat var="r" value="#{testResultController.testResult.results}" varStatus="tSt">
<h:outputText value="#{testResultController.testResult.name}: " rendered="#{tSt.first}" />
<h:outputText value="#{r.result}"/>
<h:outputText value=", " rendered="#{!tSt.last}" />
</ui:repeat>
As you can see, the JSF page accesses the Controller bean. In that bean is a PostConstruct annotation, which gets executed when the JSF page references the bean. The PostConstruct executes any code you need to initialize the bean, in this case a call to the service layer which loads a test result from the database. Of course, there is a bit of code I didn't include, such as creating a test or showing a list of CompletedTests so the user can choose which one he or she wants. You can do all that on a single page with a form and a drop-down list. Further, calling to the database every time the JSF page is loaded will result in poor performance, so there are more sophisticated mechanisms for caching Entities in memory, but that is beyond this simple answer.

JSF2.2, RequestScope and component persistence

My actual scenario is a simple JSF project that uses Mojarra 2.2.5.
I'm trying to get programmatically a component instance (via "findComponent" method or binding ...) and set some attributes (click on "ChangeColor" button).
After that, using any other action (for example clicking on "Send" button), the previous changes are ignored !!
It seems that changeColor method don't update the ViewState !
The sample code is the following:
<h:form id="form">
<h:panelGrid columns="1">
<h:inputText id="input" binding="#{page9.input}"/>
<h:commandButton value="Change BackColor" action="#{page9.changeColor}"/>
<h:commandButton value="Send" action="#{page9.dummy}" />
</h:panelGrid>
</h:form>
And the relative RequestScope bean
#ManagedBean(name="page9")
#RequestScoped
public class Page9 implements Serializable {
private static final long serialVersionUID = 1L;
private HtmlInputText input;
public HtmlInputText getInput() {
return input;
}
public void setInput(HtmlInputText input) {
this.input = input;
}
public void changeColor(){
FacesContext fc = FacesContext.getCurrentInstance();
HtmlInputText hit = (HtmlInputText) fc.getViewRoot().findComponent(":form:input");
hit.setStyle("background-color:blue");
}
public void dummy(){
}
}
Some important considerations:
1) I must use RequestScope for compatibility reasons.
2) Setting javax.faces.PARTIAL_STATE_SAVING to "false" all works fine (!).
3) Trying to use MyFaces 2.2.3 libraries all works fine (!).
What do you think about ?
Thanks.

Primefaces obtain inputText value in managedBean

My question should be trivial for someone who is familiar with Primefaces but I'm just starting. My question is:
When I put inputText component to my web page like this:
<h:form id="formularz">
<p:inputText id="workyears" value="#{appointentBean.year}" style="width: 40px;"/>
<h:form>
I would like to retrieve the inputed text directly from appointentBean. I mean I would like to create another method in appointentBean that will process inputed text so I need inputed text to be placed in referenced field year immediately. In another worlds I need my field year in appointentBean to be automaticaly updated while someone put text in inputText component. Something like submit? I hope you understand what I mean.
Here is my managedBean:
#ManagedBean
#ViewScoped
#SessionScoped
public class appointentBean{
private int year;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
//Here I will put another method that will be operate on year value
}
You can do that using events like this (read more):
<h:form>
<p:inputText value="#{viewMBean.hello}">
<p:ajax event="keyup" update="hello" process="#this" />
</p:inputText>
<h:outputText id="hello" value="#{viewMBean.hello}" />
</h:form>
Here is the viewMBean:
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class ViewMBean implements Serializable {
private String hello;
public String getHello() {
return hello;
}
public void setHello(String hello) {
this.hello = hello;
}
}
PS: Welcome to Primefaces!!

How to add multiple results to an JSF form

Hi there i currently have a web page that uses ajax on submit to display the message the user entered on the same page below the input box, what i am wondering, if it is possible to keep a record of all messages inputted such as message 1, message 2 etc all displayed under them?
what is the best method for this ? also is there a way to do this with out the user having to press the submit button each time ?
this is my code so far :
<h:body>
<h3>JSF 2.0 + Ajax Hello World Example</h3>
<h:form>
<h:inputText id="name" value="#{helloBean.name}"></h:inputText>
<h:commandButton value="Welcome Me">
<f:ajax execute="name" render="output" />
</h:commandButton>
<h2><h:outputText id="output" value="#{helloBean.sayWelcome}" /></h2>
</h:form>
</h:body>
my bean
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import java.io.Serializable;
#ManagedBean
#SessionScoped
public class HelloBean implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSayWelcome(){
//check if null?
if("".equals(name) || name ==null){
return "";
}else{
return "Ajax message : Welcome " + name;
}
}
}
First you will need to change your bean. Make the attribute a List<String> to store all of the messages.
After that, to show the list you need to change output to a component that allows for showing all elements of the List; v.g. dataTable.
Also, you will need to invoke an action method in you ajax request, because your application will need to execute some logic (add name to the list).

JSF/AJAX Dynamic Menu - 404 issue

I am trying to make a dynamic menu such that when something is selected in the first selector, the second one is populated from the database based on the selection in the first one. Here is the .xhtml:
<f:view>
<h:form>
<h:selectOneMenu id="seasonSelector" value ="#{selector_bean.season}">
<f:ajax event="valueChange" listener="#{selector_bean.genEvents}"
execute="seasonSelector" render="eventSelector" />
<f:selectItems value ="#{selector_bean.seasons}" var ="s"
itemLabel="#{s.getRange()}"
itemValue="#{s}"></f:selectItems>
</h:selectOneMenu>
<h:selectOneMenu id="eventSelector">
<f:selectItems value ="#{selector_bean.events}" var ="e"
itemLabel="#{e.event_Name}"
itemValue="#{e}"></f:selectItems>
</h:selectOneMenu>
</h:form>
</f:view>
Here is the bean:
#ManagedBean(name = "selector_bean")
#Stateless
public class selector_bean implements Serializable{
#EJB
SeasonFacade sf;
#EJB
EventFacade ef;
#EJB
WrestlerFacade wf;
private Season season;
private Event event;
private List<Event> events;
private Match match;
private Wrestler wrestler;
public List<Season> getSeasons(){
return sf.findAll();
}
public void genEvents(AjaxBehaviorEvent event){
events = (ef.findBySeason(season));
}
// setters and getters after this
When I change the value of the first selectOneMenu, a popup box appears with this message:
httpError: There was an error communicating with the server, status: 404
I am new to both JSF and AJAX so feel free to tear me apart if I am doing it wrong. Thanks for any help!
Your #ManagedBean is behaving as an EJB with the #Stateless annotation. Remove it and instead set the scope of your bean to #ViewScoped:
#ManagedBean(name = "selectorBean")
#ViewScoped
public class SelectorBean implements Serializable{
//your implementation...
}
Also, make sure to follow the JavaBean naming conventions. I've changed the name of your class to start with capital letter.

Resources