I want to create a primefaces menu component programmatically, here is the xhtml tag:
<p:menu model="#{notificationMenu.model}" />
and here is the spring component associated:
#Component
#Scope("session")
#Qualifier("notificationMenu")
public class NotificationMenu {
#Autowired
NotificationService notificationService;
private MenuModel model;
#PostConstruct
public void createMenuModel() {
List<Notification> listNotifs = notificationService.getAllUnreadNotifsForUser(LoginBean.getConnectedUser());
model = new DefaultMenuModel();
DefaultSubMenu subMenu = new DefaultSubMenu();
for (Notification notification : listNotifs) {
DefaultMenuItem item = new DefaultMenuItem();
item.setValue(notification.getTypenotification().getTypenotif());
item.setUrl("/user/index.xhtml");
subMenu.addElement(item);
}
model.addElement(subMenu);
}
public MenuModel getModel() {
return model;
}
}
I'd like to programmatically associated this menu to a graphical image (like a notification image), so that when the user click on the image the menu is shown... is it possible?
EDIT :
I want the menu to be displayed under the image and disappear on Blur (clicking outside the image).
Overlay Menu
A dynamic menu is created by setting overlay option to true and defining a trigger to show the
menu. Location of menu on page will be relative to the trigger and defined by my and at options
that take combination of four values:
left
right
bottom
top
That said:
<p:menu overlay="true" trigger="img"
my="left top"
at="bottom left"
model="#{notificationMenu.model}" />
<p:graphicImage id="img" />
Related
I'm using a custom template with a sidebar: i have 3 grouped menu that can be opened or closed. I would open a menu only when I'm on certain pages.
I tried to use a NavigationController with a property that let me understand "where" are we now so i can open the right menu.
#ManagedBean(eager = true)
#RequestScoped
public class NavigationController implements Serializable {
#ManagedProperty(value = "#{param.pageId}")
private String pageId;
public String showPage() {
switch(pageId) {
case "1": return "home";
case "21": return "cerca_a";
case "22": return "anagrafica?id_p=new&faces-redirect=true";
...
default: return "home";
}
}
//getter and setter
}
Used in sideBar.xhtml like this
<ul class="collapse list-unstyled #{navigationController.pageId lt 30? 'show':''}">
<li><h:commandLink action="#{navigationController.showPage}" value="Cerca">
<f:param name="pageId" value="31"/></h:commandLink></li>
...
</ul>
It doesn't work when I use links with params (case 22): no menu is opened, it looses #{navigationController.pageId}.
Pretty sure it happens because it is #RequestScoped and when i call anagrafica?id_p=new the AnagConverter is executed.
Should I use a #ViewScoped? How? Is there a better way to mantain a custom "breadcrumb"?
Thanks a lot!
I am using a Bean (MenuBean) to dynamically create a
<p:breadCrumb model="#{menuBean.model}" />
When transitioning through each page of my application, I push or pop pages from a "page stack", so as to adapt the breadCrumb of each page.
#ManagedBean
#SessionScoped
public class MenuBean implements Serializable {
private MenuModel model;
private int navIdx;
private ArrayList<String[]> pageStack;
#PostConstruct
public void init() {
pageStack = new ArrayList<>();
navIdx = 0;
String [] home = new String[2];
home[0] = "Home";
home[1] = "home.xhtml";
pageStack.add(home);
refreshModel();
}
private void refreshModel() {
model = new DefaultMenuModel();
int i = 0;
for(String[] s: pageStack) {
DefaultMenuItem index = new DefaultMenuItem();
index.setValue(s[0]);
index.setCommand("#{menuBean.navigate}");
index.setParam("index", String.valueOf(i++));
model.addElement(index);
}
}
private void push(String [] page) {
pageStack.add(page);
navIdx++;
refreshModel();
}
private String pop() {
pageStack.remove(navIdx--);
String[] prevPage = pageStack.get(navIdx);
refreshModel();
return prevPage[1];
}
}
In order to maintain this stack, my MenuBean is SessionScoped.
However, when I refresh the last page for example, the initial page is shown (since the url does not change) but the breadCrumb still displays the whole stack.
My question is: Is there a way to clear the MenuBean when the user leaves the page, or refreshes it?
One way you could refresh the bean is using remoteCommand with set auto run on true. So once you refresh the page remote commad will fire and call method in backing bean.
<!-- init bean on page load -->
<h:form id="initializePageDataForm">
<p:remoteCommand name="initializePageDataCommand" autoRun="true" action="#{MenuBean.init()}" />
</h:form>
This worked for me using JSF instead of Primefaces.
<!-- init bean on page load -->
<f:metadata>
<f:event type="preRenderView" listener="#{MenuBean.init() }" />
</f:metadata>
I'm using a ace:dataTable to display a list. When the user clicks a row, a detail popup is shown. What I'm trying to achieve is that the click has no effect on the selection of rows.
This is my code:
public void rowSelected(SelectEvent event) {
DataTable dataTable = (DataTable)event.getComponent();
dataTable.getStateMap().setAllSelected(false);
// Show Popup etc
// Prints an empty list
System.out.println(dataTable.getStateMap().getSelected());
}
The popup is shown, but the selection ist still there. Any Ideas?
<ace:dialog id="dialogid"
header="Header" widgetVar="nodeDialog"
modal="true" draggable="false" showEffect="true" hideEffect="true"
relativePosition="center center">
---dialog contnent---
</ace:dialog>
public void rowSelected(SelectEvent event) {
DataTable dataTable = (DataTable)event.getComponent();
dataTable.getStateMap().setAllSelected(false);
// Show Popup etc
JavascriptContext.addJavascriptCall(facesContext(), "nodeDialog.show();");
// Prints an empty list
---writwe to the dialog contnent---
System.out.println(dataTable.getStateMap().getSelected());
}
I have two buttons and I have to navigate through these nodes TreeNode in my tree.
My idea is to update the SelectedNode at each iteration the user with the buttons. But the update does not work properly and the SelectedNode remains one selected with the click. How can I do this properly?
myBean(){
...
private TreeNode selectedNode;
private TreeNode navigazione;
//Getter and Setter
.......
public void navigate(){
if(getSelectedNode!=null && getSelectedNode().getChildCount()>0){
navigazione=getSelectedNode().getChildren().get(0);
System.out.print(getNavigazione().getChildCount()+getNavigazione().getData().toString());
setSelectedNode(navigazione);
}
return;
}
xhtml portion
p:panel id="navTree" style="border:none; background:transparent; align:left"
p:commandButton icon="ui-icon-arrowthick-1-n" disabled="false" ajax="true"
actionListener="#{myBean.navigate}">/p:commandButton>
Note that the tags are opened and closed properly and not as here to display problems
Thanks!
I am reasonably new to Java/JSF development (previously Mainframe legacy) so I am hoping someone will be able to let me know if what I am about to ask is possible and how to do it. Or at least point me in the right direction.
I'm trying to create a portlet where I can add the same component over and over again up to a maximum of 30 times. Eventually the data behind these components will be different in each one but from the same database. What I've done so far is create a container component and a button which calls a method to add something to the container. Like as follows:
<h:body>
<h:form>
<ice:panelGrid binding="#{simpleBean.containerComponent}"/>
<br/>
<ice:commandButton value="add new section" action="#{simpleBean.addComponent}" />
</h:form>
</h:body>
What I'm struggling with is the backing bean to create and render the component. At the minute I am just trying to create anything that repeats. The final code will be more complex than this.
private HtmlPanelGrid containerComponent;
private int i = 1;
public void addComponent() {
UIColumn uiColumn = new UIColumn();
uiColumn.setId("UIColumn_"+i);
HtmlOutputText htmlOutputText = new HtmlOutputText();
htmlOutputText.setId("HtmlOutputText_"+i);
htmlOutputText.setValue("HtmlOutputText_1_Value");
HtmlInputText htmlInputText = new HtmlInputText();
htmlInputText.setId("HtmlInputText_"+i);
htmlInputText.setValue("HtmlInputText_1_Value");
uiColumn.getChildren().add(htmlOutputText);
uiColumn.getChildren().add(htmlInputText);
if (containerComponent == null) {
containerComponent = new HtmlPanelGrid();
}
containerComponent.getChildren().add(uiColumn);
i++;
}
I can get the code to render something the first time the button is clicked but nothing happens subsequently. In an ideal world I'd get 30 of the same component displayed on the screen.
Can anyone offer any advice?
Thank you in advance.
Chris