I have a template with button which opens dialog:
<p:commandButton
id="roles-button"
icon="fa fa-key">
<f:setPropertyActionListener value="#{user}" target="#{userAdministrationView.selectedUser}" />
<f:actionListener binding="#{userAdministrationView.openUserRolesDialogWithParameters()}"/>
<p:ajax
event="dialogReturn"
listener="#{dialogHandler.showMessage}"
update=":user-administration-form:user-administration-table"
global="false"
/>
</p:commandButton>
Backing bean for template (userAdministrationView) is #ViewScoped.
I want to pass parameter selectedUser to the dialog. Is it possible with using Faces.setContext/Request/FlashAttribute, like adviced here? I tried to implement it like:
public void openUserRolesDialogWithParameters() {
Faces.setContextAttribute("user", selectedUser);
dialogHandler.openDialog("user-roles-dialog");
}
and in dialogs backing bean (which is #ViewScoped too):
#PostConstruct
public void init() {
this.user = Faces.getContextAttribute("user");
...
}
but I get null in user. The same result is with setRequestAttribute and setFlashAttribute.
Here it is suggested to create #SessionScoped bean with properties, but this decision looks not very relevant for me. Is it the only way?
Thanks to BalusC, i started to search in right direction, and I found this explanation.
So, it works like this:
template backing bean :
public void openUserRolesDialogWithParameters() {
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
sessionMap.put("user", selectedUser);
dialogHandler.openDialog("user-roles-dialog", "contentWidth", "500");
}
dialog backing bean:
#PostConstruct
public void init() {
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
this.user = (UserModel) sessionMap.get("user");
sessionMap.remove("user");
...
}
Related
I am using:
JSF: 2.2.13
Primefaces: 6.2
PROBLEM: When I make "ImageView" bean #ViewScoped then my file downloads after pressing the button. When I make "ImageView" bean #RequestScoped then my file doesn't download and the app simply opens a new page (the current page) without any URL params (so just opens http://localhost:8080/imageView.jsf)
SUSPECTED PROBLEM: Maybe <f:param> sends diffrent things depending if the ImageView is #ViewScoped vs #RequestScope
I open the page with the following GET REQUEST http://localhost:8080/imageView.jsf?contentFileId=1
I have the following code:
<h:form id="form">
<p:commandButton id="btn" value="Download"
icon="fa fa-download" ajax="false">
<f:param name="contentFileId" value="#{imageView.contentFileId}" />
<p:fileDownload value="#{streamedContentView.image}"/>
</p:commandButton>
</h:form>
The beans:
ImageView
#Named
#RequestScoped
public class ImageView implements Serializable {
private String contentFileId;
#PostConstruct
private void init() {
HttpServletRequest request = (HttpServletRequest) FacesContext
.getCurrentInstance()
.getExternalContext()
.getRequest();
contentFileId = request.getParameter("contentFileId");
}
//...GETTERS & SETTERS
}
StreamedContentView
#Named
#ApplicationScoped
public class StreamedContentView {
#Inject
ContentFileManager contentFileManager;
public StreamedContent getImage() throws URISyntaxException, IOException {
//Get id of file
FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> requestParameterMap = context.getExternalContext().getRequestParameterMap();
String rawContentFileId = requestParameterMap.get("contentFileId");
//Get file
ContentFile contentFile = contentFileManager.findById(Long.parseLong(rawContentFileId));
InputStream stream = new ByteArrayInputStream(contentFile.getContents());
return new DefaultStreamedContent(stream, contentFile.getMimeType(), contentFile.getFileName());
}
}
Can I add JSF components dynamically? I need to have a form with a button which should add one <h:inputText> to the form. Is this possible?
I know this should be possible in JavaScript somehow. Do anybody know how to do this in JSF? I think the major problem is how do I get or set values of new inputs via #{value}.
Use an iterating component like <h:dataTable> or <ui:repeat> to display a dynamically sized List of entities. Make the bean #ViewScoped to ensure that the list is remembered across postbacks on the same view instead of recreated over and over.
Kickoff example with <h:dataTable> (when using <ui:repeat> simply replace <h:dataTable> by <ui:repeat>, and <h:column> by e.g. <li> or <div>):
<h:form>
<h:dataTable value="#{bean.items}" var="item">
<h:column><h:inputText value="#{item.value}" /></h:column>
<h:column><h:commandButton value="remove" action="#{bean.remove(item)}" /></h:column>
</h:dataTable>
<h:commandButton value="add" action="#{bean.add}" />
<h:commandButton value="save" action="#{bean.save}" />
</h:form>
Managed bean:
#Named
#ViewScoped
public class Bean {
private List<Item> items;
#PostConstruct
public void init() {
items = new ArrayList<>();
}
public void add() {
items.add(new Item());
}
public void remove(Item item) {
items.remove(item);
}
public void save() {
System.out.println("items: " + items);
}
public List<Item> getItems() {
return items;
}
}
Model:
public class Item {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String toString() {
return String.format("Item[value=%s]", value);
}
}
See also:
Recommended JSF 2.0 CRUD frameworks
How to create dynamic JSF form fields
How to implement a dynamic list with a JSF 2.0 Composite Component?
How to choose the right bean scope?
It's should be like that
Bind a form tag to the bean property
<form binding="#{myBean.myform}">...</form>
#ManagedBean("myBean")
public class Bean{
property HtmlForm myform;
}
on event, create a new instance of the input component
HtmlInputText input=new HtmlInputText();
and attach to the your form
myform.getChildren().add(input);
Use h:dataTable to add elements dynamically... Have a list of any type you want to provide values for dataTable...
In h:dataTable... you can include the element tag to create inside <h:column>
It will be used to generate elements you want to create dynamically.
I have a <p:dataTable> as follows.
<p:dataTable var="row" value="#{testManagedBean.list}">
<p:column>
<h:outputText value="#{row.subCatId}"/>
</p:column>
<p:column>
<p:commandLink process="#this">
<h:outputText value="#{row.subCatName}"/>
<f:setPropertyActionListener target="#{testManagedBean.subCatName}" value="#{row.subCatName}"/>
</p:commandLink>
</p:column>
</p:dataTable>
The corresponding RequestScoped managed bean is as follows.
#ManagedBean
#RequestScoped
public final class TestManagedBean
{
#EJB
private final TestBeanLocal testService=null;
private List<SubCategory>list;
private String subCatName;
#PostConstruct
private void init()
{
list=testService.getSubCategoryList();
}
public List<SubCategory> getList() {
return list;
}
public String getSubCatName() {
return subCatName;
}
public void setSubCatName(String subCatName) {
System.out.println("setSubCatName() called : "+subCatName);
this.subCatName = subCatName;
}
}
When <p:commandLink> inside <p:dataTable> is clicked, the corresponding setter method associated with <f:setProperyActionListener> (setSubCatName()) is called and the value is correctly set to the target property which is subCatName in this managed bean.
I have avoided many things like paging to have a minimal example.
Now, I need to populate this <p:dataTable> lazily. I'm changing this <p:dataTable> and the corresponding managed bean as follows.
<p:dataTable var="row" value="#{testManagedBean}" lazy="true" rows="10" rowIndexVar="rowIndex">
<p:column>
<h:outputText value="#{row.subCatId}"/>
</p:column>
<p:column>
<p:commandLink process="#this">
<h:outputText value="#{row.subCatName}"/>
<f:setPropertyActionListener target="#{testManagedBean.subCatName}" value="#{row.subCatName}"/>
</p:commandLink>
</p:column>
</p:dataTable>
And the associated JSF managed is given below.
#ManagedBean
#RequestScoped
public final class TestManagedBean extends LazyDataModel<SubCategory> implements Serializable
{
#EJB
private final TestBeanLocal testService=null;
private String subCatName;
private static final long serialVersionUID = 1L;
public String getSubCatName() {
return subCatName;
}
public void setSubCatName(String subCatName) {
System.out.println("setSubCatName() called : "+subCatName);
this.subCatName = subCatName;
}
#Override
public List<SubCategory> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters)
{
setRowCount(4); //Just an example. Otherwise, fetch from the database.
return testService.getSubCategoryList(first, pageSize, sortField, sortOrder, filters);
}
}
Now, when <p:commandLink> inside <p:dataTable> is clicked, the corresponding setter method associated with <f:setProperyActionListener> (setSubCatName()) is not invoked.
The setSubCatName() is only invoked, when the managed bean is decorated with a broader scope like #ViewScoped (in case of lazy is set to true)
Why doesn't <f:setPropertyActionListener> work with a request scoped managed managed bean, when a <p:dataTable> (also true for <p:dataGrid>) is lazily loaded?
Is it mandatory to designate a managed bean with a broader than a request scope in such cases?
yes it is mandatory because the underlying model has to be the same instance. even if it has the same values it won't work.
like you, i've met this behavior: primefaces datatable lazy loading and commandbutton per row
I'm having troubles with view scoped bean.
I have commandbutton in xhtml, with associated action in managed bean which is supposed to render the same view again. Action method returns fine, but no view is rendered, it's stuck with "waiting for localhost" message in browser. For some reason bean's #PreDestroy method and #PostConstruct methods of ejb injected in it are called multiple times ( it seems infinetely).
If I change the bean to Sessionscoped, everything works fine.
I'm using netbeans 7.2.1, working on web application with added JSF framework.
xhtml part:
<h:form id="getmovie" >
<h:panelGrid id="movienameform" columns="3" rendered="#{!MovieBean.choseMovie}">
<h:outputLabel for="moviename" value="Movie name: "/>
<h:inputText id="moviename" value="#{MovieBean.name}"/>
<h:commandButton value="submit" action="#{MovieBean.checkMovieExists()}">
</h:commandButton>
</h:panelGrid>
</h:form>
backing bean:
#Named(value = "MovieBean")
#ViewScoped
public class MovieBean implements Serializable {
private String name;
private boolean exist;
private boolean searched = false;
private boolean choseMovie = false;
#EJB
MovieejbLocal movieejb;
ScreenejbLocal screenejb;
public String checkMovieExists() {
setExist(getMovieejb().checkMovieExists(getName()));
searched = true;
return null;
}
...
}
and ejb
#Stateful
#Local(MovieejbLocal.class)
public class Movieejb implements MovieejbLocal {
....
}
I need this bean to be view scoped and not session scoped.
Any ideas what is wrong with viewScoped here?
I've seen this question: #ViewScoped Managed bean loads many times during postback, but solution there doesn't work for me.
Thanks!
Can I add JSF components dynamically? I need to have a form with a button which should add one <h:inputText> to the form. Is this possible?
I know this should be possible in JavaScript somehow. Do anybody know how to do this in JSF? I think the major problem is how do I get or set values of new inputs via #{value}.
Use an iterating component like <h:dataTable> or <ui:repeat> to display a dynamically sized List of entities. Make the bean #ViewScoped to ensure that the list is remembered across postbacks on the same view instead of recreated over and over.
Kickoff example with <h:dataTable> (when using <ui:repeat> simply replace <h:dataTable> by <ui:repeat>, and <h:column> by e.g. <li> or <div>):
<h:form>
<h:dataTable value="#{bean.items}" var="item">
<h:column><h:inputText value="#{item.value}" /></h:column>
<h:column><h:commandButton value="remove" action="#{bean.remove(item)}" /></h:column>
</h:dataTable>
<h:commandButton value="add" action="#{bean.add}" />
<h:commandButton value="save" action="#{bean.save}" />
</h:form>
Managed bean:
#Named
#ViewScoped
public class Bean {
private List<Item> items;
#PostConstruct
public void init() {
items = new ArrayList<>();
}
public void add() {
items.add(new Item());
}
public void remove(Item item) {
items.remove(item);
}
public void save() {
System.out.println("items: " + items);
}
public List<Item> getItems() {
return items;
}
}
Model:
public class Item {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String toString() {
return String.format("Item[value=%s]", value);
}
}
See also:
Recommended JSF 2.0 CRUD frameworks
How to create dynamic JSF form fields
How to implement a dynamic list with a JSF 2.0 Composite Component?
How to choose the right bean scope?
It's should be like that
Bind a form tag to the bean property
<form binding="#{myBean.myform}">...</form>
#ManagedBean("myBean")
public class Bean{
property HtmlForm myform;
}
on event, create a new instance of the input component
HtmlInputText input=new HtmlInputText();
and attach to the your form
myform.getChildren().add(input);
Use h:dataTable to add elements dynamically... Have a list of any type you want to provide values for dataTable...
In h:dataTable... you can include the element tag to create inside <h:column>
It will be used to generate elements you want to create dynamically.