问题
Am using primefaces 5.3. I am generating a primefaces menu dynamically. I want to set the id on the menu elements so that I can display a tooltip based on that id. My code is:
DefaultMenuModel menuModel = new DefaultMenuModel();
DefaultMenuItem homeMenuItem = new DefaultMenuItem( "Hello");
homeMenuItem.setIcon("fa fa-home");
homeMenuItem.setTitle("halloo");
//Setting the id here
homeMenuItem.setId("homeId");
menuModel.addElement(homeMenuItem);
However when I view the page source or inspect the element there is no id set on that menu item. Is there some other way to set the id on a menu element?
回答1:
This doesn't work in PrimeFaces. I already opened an issue ticket but it isn't solved yet. If you check the sourcecode you will see, that it sets your chosen id first, but then it overrides it again in the backend. So there is no chance to set an id programatically at the moment.
You can get elements by style class via javascript if that solves your problem.
Here you can see a similar question with the ticket number: Id of menuitem is not rendered
回答2:
I did a workaround which worked for me so far. Maybe ist helps you too:
You have to override the Primefaces classes with Custom Classes of your own. Here is my example:
Add this to faces-config.xml
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.PanelMenuRenderer</renderer-type>
<renderer-class>mypath.CustomPanelMenuRenderer</renderer-class>
</renderer></render-kit>
then I added the two overwritten classes:
CustomPanelMenuRenderer:
public class CustomPanelMenuRenderer extends CustomBaseMenuRenderer {
@Override
protected void encodeScript(FacesContext context, AbstractMenu abstractMenu) throws IOException {
PanelMenu menu = (PanelMenu) abstractMenu;
String clientId = menu.getClientId(context);
WidgetBuilder wb = getWidgetBuilder(context);
wb.initWithDomReady("PanelMenu", menu.resolveWidgetVar(), clientId)
.attr("stateful", menu.isStateful());
wb.finish();
}
@Override
protected void encodeMarkup(FacesContext context, AbstractMenu abstractMenu) throws IOException {
ResponseWriter writer = context.getResponseWriter();
PanelMenu menu = (PanelMenu) abstractMenu;
String clientId = menu.getClientId(context);
String style = menu.getStyle();
String styleClass = menu.getStyleClass();
styleClass = styleClass == null ? PanelMenu.CONTAINER_CLASS : PanelMenu.CONTAINER_CLASS + " " + styleClass;
writer.startElement("div", menu);
writer.writeAttribute("id", clientId, "id");
writer.writeAttribute("class", styleClass, "styleClass");
if (style != null) {
writer.writeAttribute("style", style, "style");
}
writer.writeAttribute("role", "menu", null);
if (menu.getElementsCount() > 0) {
List<MenuElement> elements = menu.getElements();
for (MenuElement element : elements) {
if (element.isRendered() && element instanceof Submenu) {
encodeRootSubmenu(context, menu, (Submenu) element);
}
}
}
writer.endElement("div");
}
protected void encodeRootSubmenu(FacesContext context, PanelMenu menu, Submenu submenu) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String style = submenu.getStyle();
String styleClass = submenu.getStyleClass();
styleClass = styleClass == null ? PanelMenu.PANEL_CLASS : PanelMenu.PANEL_CLASS + " " + styleClass;
boolean expanded = submenu.isExpanded();
String headerClass = expanded ? PanelMenu.ACTIVE_HEADER_CLASS : PanelMenu.INACTIVE_HEADER_CLASS;
String headerIconClass = expanded ? PanelMenu.ACTIVE_TAB_HEADER_ICON_CLASS : PanelMenu.INACTIVE_TAB_HEADER_ICON_CLASS;
String contentClass = expanded ? PanelMenu.ACTIVE_ROOT_SUBMENU_CONTENT : PanelMenu.INACTIVE_ROOT_SUBMENU_CONTENT;
//wrapper
writer.startElement("div", null);
writer.writeAttribute("class", styleClass, null);
if (style != null) {
writer.writeAttribute("style", style, null);
}
if (submenu.getClientId() != null) {
writer.writeAttribute("id", submenu.getClientId(), null);
}
//header
writer.startElement("h3", null);
writer.writeAttribute("class", headerClass, null);
writer.writeAttribute("role", "tab", null);
writer.writeAttribute("tabindex", "0", null);
//icon
writer.startElement("span", null);
writer.writeAttribute("class", headerIconClass, null);
writer.endElement("span");
writer.startElement("a", null);
writer.writeAttribute("href", "#", null);
writer.writeAttribute("tabindex", "-1", null);
writer.writeText(submenu.getLabel(), null);
writer.endElement("a");
writer.endElement("h3");
//content
writer.startElement("div", null);
writer.writeAttribute("class", contentClass, null);
writer.writeAttribute("role", "tabpanel", null);
writer.writeAttribute("id", menu.getClientId(context) + "_" + submenu.getId(), null);
writer.writeAttribute("tabindex", "0", null);
if (submenu.getElementsCount() > 0) {
List<MenuElement> elements = submenu.getElements();
writer.startElement("ul", null);
writer.writeAttribute("class", PanelMenu.LIST_CLASS, null);
for (MenuElement element : elements) {
if (element.isRendered()) {
if (element instanceof MenuItem) {
MenuItem menuItem = (MenuItem) element;
String containerStyle = menuItem.getContainerStyle();
String containerStyleClass = menuItem.getContainerStyleClass();
containerStyleClass = (containerStyleClass == null) ? Menu.MENUITEM_CLASS : Menu.MENUITEM_CLASS + " " + containerStyleClass;
writer.startElement("li", null);
writer.writeAttribute("class", containerStyleClass, null);
if (element.getId() != null) {
writer.writeAttribute("id", element.getId(), null);
}
if (containerStyle != null) {
writer.writeAttribute("style", containerStyle, null);
}
encodeMenuItem(context, menu, menuItem);
writer.endElement("li");
}
else if (element instanceof Submenu) {
encodeDescendantSubmenu(context, menu, (Submenu) element);
}
}
}
writer.endElement("ul");
}
writer.endElement("div"); //content
writer.endElement("div"); //wrapper
}
protected void encodeDescendantSubmenu(FacesContext context, PanelMenu menu, Submenu submenu) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String icon = submenu.getIcon();
String style = submenu.getStyle();
String styleClass = submenu.getStyleClass();
styleClass = styleClass == null ? PanelMenu.DESCENDANT_SUBMENU_CLASS : PanelMenu.DESCENDANT_SUBMENU_CLASS + " " + styleClass;
boolean expanded = submenu.isExpanded();
String toggleIconClass = expanded ? PanelMenu.DESCENDANT_SUBMENU_EXPANDED_ICON_CLASS : PanelMenu.DESCENDANT_SUBMENU_COLLAPSED_ICON_CLASS;
String listClass = expanded ? PanelMenu.DESCENDANT_SUBMENU_EXPANDED_LIST_CLASS : PanelMenu.DESCENDANT_SUBMENU_COLLAPSED_LIST_CLASS;
boolean hasIcon = (icon != null);
String linkClass = (hasIcon) ? PanelMenu.MENUITEM_LINK_WITH_ICON_CLASS : PanelMenu.MENUITEM_LINK_CLASS;
writer.startElement("li", null);
writer.writeAttribute("id", submenu.getClientId(), null);
writer.writeAttribute("class", styleClass, null);
if (style != null) {
writer.writeAttribute("style", style, null);
}
writer.startElement("a", null);
writer.writeAttribute("class", linkClass, null);
//toggle icon
writer.startElement("span", null);
writer.writeAttribute("class", toggleIconClass, null);
writer.endElement("span");
//user icon
if (hasIcon) {
writer.startElement("span", null);
writer.writeAttribute("class", "ui-icon " + icon, null);
writer.endElement("span");
}
//submenu label
writer.startElement("span", null);
writer.writeAttribute("class", PanelMenu.MENUITEM_TEXT_CLASS, null);
writer.writeText(submenu.getLabel(), null);
writer.endElement("span");
writer.endElement("a");
//submenu children
if (submenu.getElementsCount() > 0) {
List<MenuElement> elements = submenu.getElements();
writer.startElement("ul", null);
writer.writeAttribute("class", listClass, null);
for (MenuElement element : elements) {
if (element.isRendered()) {
if (element instanceof MenuItem) {
writer.startElement("li", null);
writer.writeAttribute("class", Menu.MENUITEM_CLASS, null);
encodeMenuItem(context, menu, (MenuItem) element);
writer.endElement("li");
}
else if (element instanceof Submenu) {
encodeDescendantSubmenu(context, menu, (Submenu) element);
}
}
}
writer.endElement("ul");
}
writer.endElement("li");
}
}
and CustomBaseMenuRenderer:
public class CustomBaseMenuRenderer extends BaseMenuRenderer {
@Override
protected void encodeMenuItem(FacesContext context, AbstractMenu menu, MenuItem menuitem) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String title = menuitem.getTitle();
String style = menuitem.getStyle();
boolean disabled = menuitem.isDisabled();
writer.startElement("a", null);
writer.writeAttribute("tabindex", "-1", null);
if (shouldRenderId(menuitem)) {
writer.writeAttribute("id", menuitem.getClientId(), null);
}
if (title != null) {
writer.writeAttribute("title", title, null);
}
String styleClass = this.getLinkStyleClass(menuitem);
if (disabled) {
styleClass = styleClass + " ui-state-disabled";
}
writer.writeAttribute("class", styleClass, null);
if (style != null) {
writer.writeAttribute("style", style, null);
}
if (disabled) {
writer.writeAttribute("href", "#", null);
writer.writeAttribute("onclick", "return false;", null);
}
else {
setConfirmationScript(context, menuitem);
String onclick = menuitem.getOnclick();
//GET
if (menuitem.getUrl() != null || menuitem.getOutcome() != null) {
String targetURL = getTargetURL(context, (UIOutcomeTarget) menuitem);
writer.writeAttribute("href", targetURL, null);
if (menuitem.getTarget() != null) {
writer.writeAttribute("target", menuitem.getTarget(), null);
}
}
//POST
else {
writer.writeAttribute("href", "#", null);
UIComponent form = ComponentTraversalUtils.closestForm(context, menu);
if (form == null) {
throw new FacesException("MenuItem must be inside a form element");
}
String command;
if (menuitem.isDynamic()) {
String menuClientId = menu.getClientId(context);
Map<String, List<String>> params = menuitem.getParams();
if (params == null) {
params = new LinkedHashMap<String, List<String>>();
}
List<String> idParams = new ArrayList<String>();
idParams.add(menuitem.getId());
params.put(menuClientId + "_menuid", idParams);
command = menuitem.isAjax() ? buildAjaxRequest(context, menu, (AjaxSource) menuitem, form, params) : buildNonAjaxRequest(context, menu, form, menuClientId, params, true);
}
else {
command = menuitem.isAjax() ? buildAjaxRequest(context, (AjaxSource) menuitem, form)
: buildNonAjaxRequest(context, ((UIComponent) menuitem), form, ((UIComponent) menuitem).getClientId(context), true);
}
onclick = (onclick == null) ? command : onclick + ";" + command;
}
if (onclick != null) {
if (menuitem.requiresConfirmation()) {
writer.writeAttribute("data-pfconfirmcommand", onclick, null);
writer.writeAttribute("onclick", menuitem.getConfirmationScript(), "onclick");
}
else {
writer.writeAttribute("onclick", onclick, null);
}
}
}
encodeMenuItemContent(context, menu, menuitem);
writer.endElement("a");
}
@Override
protected boolean shouldRenderId(MenuElement element) {
if (element instanceof UIComponent) {
return shouldWriteId((UIComponent) element);
}
return false;
}
@Override
protected void encodeMarkup(FacesContext context, AbstractMenu abstractMenu) throws IOException {
// TODO Auto-generated method stub
}
@Override
protected void encodeScript(FacesContext context, AbstractMenu abstractMenu) throws IOException {
// TODO Auto-generated method stub
}
}
now you should be able to set Ids in the backend as expected.
来源:https://stackoverflow.com/questions/39154557/setting-id-for-a-dynamic-menu-element-in-primefaces-does-not-work