首页 > 解决方案 > 如何构建 Bootfaces动态的

问题描述

我的应用程序基于 JSF 2.2 和 Primefaces 6.2。我需要创建一个菜单栏,其中子菜单将显示在“下拉菜单”中,而不是下拉菜单中。我无法在 Primefaces 中实现这种下拉效果,不得不使用 Bootsfaces 的<b:dropMenu>组件,该组件为此提供了“drop”属性(drop="up" 创建了一个下拉)。更多信息: https ://showcase.bootsfaces.net/layout/navbars.jsf

使用<b:dropMenu>,它会以这种方式呈现,这对我来说看起来不错: Screenshot。但是,我需要<b:dropMenu>通过 Java 代码动态构建。

是否可以使用某种模型属性<b:dropMenu>,类似于 Primefaces 菜单?

在我当前的代码中,我以这种方式对子菜单进行了硬编码,我想将其删除并动态构建:

<b:navBar inverse="true" fluid="true" >
    <b:navbarLinks >
        <b:dropMenu value="Vehicle Services" drop="up" >
            <b:navLink value="Repairs" href="#"></b:navLink>
            <b:navLink value="Sales" href="#"></b:navLink>
            <b:navLink value="Financing" href="#"></b:navLink>
            <b:navLink value="Insurance" href="#"></b:navLink>
            <b:navLink value="Leasing" href="#"></b:navLink>
            <b:navLink value="Driving School" href="#"></b:navLink>
            <b:navLink value="Legal" href="#"></b:navLink>
        </b:dropMenu>
        .........
        .........
        .........

- 编辑 -

遵循@Selaron 的代码示例,尝试从<b:NavBarLinks>XHTML 中动态构建:

<h:form>
    <b:navBar inverse="true" fluid="true">
        <b:navbarLinks>
             <f:event listener="#{extranetController.initializeNavBarLinksChildren}" type="postAddToView" />
        </b:navbarLinks>
    </b:navBar>
</h:form> 

在豆子里:

public void initializeNavBarLinksChildren(ComponentSystemEvent e) {
    UIComponent component = e.getComponent();
    //assert that its a NavBarLinks

    DropMenu dropMenu = new DropMenu();
    dropMenu.setDrop("up");
    dropMenu.setValueExpression("value", Utility.createValueExpression("Vehicle Services", String.class));

    NavLink navLink1 = new NavLink();
    navLink1.setValue("Free Service");
    navLink1.setHref("#");
    dropMenu.getChildren().add(navLink1);

    NavLink navLink2 = new NavLink();
    navLink2.setValue("Paid Service");
    navLink2.setHref("#");
    dropMenu.getChildren().add(navLink2);

    component.getChildren().add(dropMenu);
}

在我正在使用的 Utility.createValueExpression() 中......意图是将字符串设置为 valueExpression:

public static ValueExpression createValuExpression(String expression, Class clazz) {
        FacesContext fc = FacesContext.getCurrentInstance();
        ELContext elContext = fc.getELContext();
        ExpressionFactory expFactory = fc.getApplication().getExpressionFactory();
        ValueExpression ret = expFactory.createValueExpression(elContext, expression, clazz);

        return ret;
    }

遗憾的是,在 UI 上,只有 DropMenu 出现(即“Vehicle Services”),但我在它下定义的两个 NavLink 都没有出现。我不太确定我做错了什么。我怀疑它是否与我为 DropMenu 设置 valueExpression 的方式有关(尽管“车辆服务”的值确实与向上的插入符号图标一起显示得很好。)

标签: primefacesjsf-2.2bootsfaces

解决方案


我没有找到允许以 PrimeFaces 方式指定动态菜单模型的属性,但这里有一个解决方法:

<h:form>
    <b:navBar inverse="true" fluid="true">
        <b:navbarLinks>
            <b:dropMenu value="Vehicle Services" drop="up">
                <f:event listener="#{myBean.initializeDropMenuChildren}"
                    type="postAddToView" />
            </b:dropMenu>
        </b:navbarLinks>
    </b:navBar>
</h:form>

这会注册一个事件侦听器 ( f:event),一旦b:dropMenu添加到视图中就会触发一次。然后,您可以动态实例化并添加指向该菜单的链接:

package my.package;

import javax.faces.component.UIComponent;
import javax.faces.event.ComponentSystemEvent;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

import net.bootsfaces.component.dropMenu.DropMenu;
import net.bootsfaces.component.navLink.NavLink;

@Named
@RequestScoped
public class MyBean {

    public void initializeDropMenuChildren(ComponentSystemEvent e) {
        UIComponent component = e.getComponent();
        assert component instanceof DropMenu;

        NavLink navLink = new NavLink();
        navLink.setValue("wow");
        navLink.setHref("#");
        component.getChildren().add(navLink);

    }

}

编辑:

作为对您的编辑的回应:看起来b:navbarLinks组件不喜欢在 xhtml 中以某种方式完全为空。尝试将 f:event 直接添加到b:navBar并从那里添加所有子项。或将您的标记更改为:

<h:form>
    <b:navBar>
        <b:navbarLinks>
            <b:dropMenu value="dummy" drop="down"/>
            <f:event listener="#{myBean.initializeDropMenuChildren}"
                type="postAddToView" />
        </b:navbarLinks>
    </b:navBar>
</h:form>

在添加你的之前dropMenus,做一个component.getChildren().clear();删除假人dropMenu


推荐阅读