您在 Backend 中设置的 Id 在 PrimeFaces 类 BaseMenuRenderer 中再次被覆盖,encodeEnd() 和 generateUniqueIds(..)
我为 https://github.com/primefaces/primefaces/issues/1039 打开了一个问题。
如果您愿意,请点赞。似乎是一个 PrimeFaces 错误。
它仍然存在于 PrimeFaces 5.3.5
所以答案是,目前无法为 MenuItems 设置 ID。
这是我目前设置 ID 的解决方法:
把它放在你的 faces-config.xml 中以使用你自己的 MenuRenderer
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.MenuRenderer</renderer-type>
<renderer-class>de.yourPackage.CustomMenuRenderer</renderer-class>
</renderer>
</render-kit>
然后创建一个像这样的 CustomMenuRenderer 类,它只做了一点改动而不是覆盖 IDS:
public class CustomMenuRenderer extends CustomBaseMenuRenderer {
protected void encodeScript(FacesContext context, AbstractMenu abstractMenu) throws IOException {
Menu menu = (Menu) abstractMenu;
String clientId = menu.getClientId(context);
WidgetBuilder wb = getWidgetBuilder(context);
wb.initWithDomReady("PlainMenu", menu.resolveWidgetVar(), clientId)
.attr("toggleable", menu.isToggleable(), false);
if (menu.isOverlay()) {
encodeOverlayConfig(context, menu, wb);
}
wb.finish();
}
protected void encodeMarkup(FacesContext context, AbstractMenu abstractMenu) throws IOException {
ResponseWriter writer = context.getResponseWriter();
Menu menu = (Menu) abstractMenu;
String clientId = menu.getClientId(context);
String style = menu.getStyle();
String styleClass = menu.getStyleClass();
String defaultStyleClass = menu.isOverlay() ? Menu.DYNAMIC_CONTAINER_CLASS : Menu.STATIC_CONTAINER_CLASS;
if (menu.isToggleable()) {
defaultStyleClass = defaultStyleClass + " " + Menu.TOGGLEABLE_MENU_CLASS;
}
styleClass = styleClass == null ? defaultStyleClass : defaultStyleClass + " " + 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);
encodeKeyboardTarget(context, menu);
if (menu.getElementsCount() > 0) {
writer.startElement("ul", null);
writer.writeAttribute("class", Menu.LIST_CLASS, null);
encodeElements(context, menu, menu.getElements());
writer.endElement("ul");
}
writer.endElement("div");
}
protected void encodeElements(FacesContext context, Menu menu, List<MenuElement> elements) throws IOException {
ResponseWriter writer = context.getResponseWriter();
boolean toggleable = menu.isToggleable();
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;
if (toggleable) {
UIComponent parent = ((UIComponent) menuItem).getParent();
containerStyleClass = (parent instanceof Submenu) ? containerStyleClass + " " + Menu.SUBMENU_CHILD_CLASS : containerStyleClass;
}
writer.startElement("li", null);
writer.writeAttribute("class", containerStyleClass, null);
writer.writeAttribute("role", "menuitem", null);
if (containerStyle != null) {
writer.writeAttribute("style", containerStyle, null);
}
if (menuItem.getId() != null) {
writer.writeAttribute("id", menuItem.getId(), null);
}
encodeMenuItem(context, menu, menuItem);
writer.endElement("li");
}
else if (element instanceof Submenu) {
encodeSubmenu(context, menu, (Submenu) element);
}
else if (element instanceof Separator) {
encodeSeparator(context, (Separator) element);
}
}
}
}
@SuppressWarnings("unchecked")
protected void encodeSubmenu(FacesContext context, Menu menu, Submenu submenu) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String label = submenu.getLabel();
String icon = submenu.getIcon();
String style = submenu.getStyle();
String styleClass = submenu.getStyleClass();
styleClass = styleClass == null ? Menu.SUBMENU_TITLE_CLASS : Menu.SUBMENU_TITLE_CLASS + " " + styleClass;
boolean toggleable = menu.isToggleable();
//title
writer.startElement("li", null);
if (toggleable) {
writer.writeAttribute("id", submenu.getClientId(), null);
}
writer.writeAttribute("class", styleClass, null);
if (style != null) {
writer.writeAttribute("style", style, null);
}
if (menu.getId() != null) {
writer.writeAttribute("id", menu.getId(), null);
}
writer.startElement("h3", null);
if (menu.isToggleable()) {
encodeIcon(context, label, Menu.EXPANDED_SUBMENU_HEADER_ICON_CLASS);
}
if (icon != null) {
encodeIcon(context, label, "ui-submenu-icon ui-icon " + icon);
}
if (label != null) {
writer.writeText(label, "value");
}
writer.endElement("h3");
writer.endElement("li");
encodeElements(context, menu, submenu.getElements());
}
protected void encodeIcon(FacesContext context, String label, String styleClass) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("span", null);
writer.writeAttribute("class", styleClass, null);
writer.endElement("span");
}
}
最后,您还需要自己的 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
}
}
我用这个已经 2 年了,它就像一个魅力。
但是很遗憾,他们还没有修复它。