Как динамически создавать Bootfaces <b: dropmenu> - PullRequest
0 голосов
/ 12 июня 2019

Мое приложение основано на JSF 2.2 и Primefaces 6.2. Мне нужно создать строку меню, где подменю будет отображаться в раскрывающемся меню, а не в раскрывающемся списке. Я не смог добиться этого эффекта выпадения в Primefaces, и мне пришлось воспользоваться компонентом Bootsfaces <b:dropMenu>, который предлагает для этой цели атрибут «drop» (drop = «up» создает выпадающий список). Больше здесь: https://showcase.bootsfaces.net/layout/navbars.jsf

Используя <b:dropMenu>, он визуализируется таким образом, что выглядит хорошо для меня: Скриншот . Однако мне нужно построить <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;
    }

К сожалению, в пользовательском интерфейсе появляется только DropMenu (т. Е. «Службы транспортных средств»), но нет ни одного из двух NavLink, которые я определил под ним. Я не очень уверен, что я делаю неправильно. Я сомневаюсь, что это как-то связано с тем, как я устанавливаю valueExpression для DropMenu (хотя значение «Vehicle Services» действительно хорошо отображается вместе со значком «вверх»).

1 Ответ

1 голос
/ 12 июня 2019

Я не нашел атрибута, позволяющего задавать модель динамического меню способом 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);

    }

}

EDIT:

В ответ на ваше редактирование: похоже, компонент b:navbarLinks не любит как-то быть полностью пустым в xhtml. Попробуйте добавить событие f: непосредственно в 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.

...