0

I have created a custom JSF component with the following code:

@FacesComponent("MainMenu")
public class MenuComponent extends UIComponentBase {
    private List<MenuItem> items;
    private String title;

    public MenuComponent() {
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public List<MenuItem> getItems() {
        return items;
    }

    public void setItems(List<MenuItem> items) {
        this.items = items;
    }

    public String getFamily() {
        return UI.FAMILY;
    }
}

Then I added a renderer for component:

@FacesRenderer(componentFamily = UI.FAMILY, rendererType = "MainMenuRenderer")
public class MenuComponentRenderer extends Renderer {
    @Override
    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
        MenuComponent menuComponent = (MenuComponent) component;
        ResponseWriter responseWriter = context.getResponseWriter();
        responseWriter.startElement("ul", menuComponent);
        responseWriter.writeAttribute("class", "sidebar-menu", "");
        // заголовок
        responseWriter.startElement("li", menuComponent);
        responseWriter.writeAttribute("class", "header", "");
        responseWriter.write(menuComponent.getTitle());
    }

    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        MenuComponent menuComponent = (MenuComponent) component;
        ResponseWriter responseWriter = context.getResponseWriter();
        responseWriter.endElement("ul");
        // title
        responseWriter.endElement("li");
        // menu items
        for (MenuItem menuItem : menuComponent.getItems()) {
        responseWriter.startElement("li", menuComponent);
    }
    }
}

Then registered component in taglib.xml:

<tag>
    <tag-name>mainMenu</tag-name>
    <component>
        <component-type>MainMenu</component-type>
        <renderer-type>MainMenuRenderer</renderer-type>
    </component>
    <attribute>
        <name>items</name>
        <required>true</required>
    </attribute>
    <attribute>
        <name>title</name>
        <required>true</required>
    </attribute>
</tag>

In JSF page I used it in the following way:

<mds:mainMenu items="${sidebar.menuItems}" title="Главное меню"</mds:mainMenu>

Tag is related with sidebar managed bean, bean is simple as possible:

@ManagedBean(name = "sidebar", eager = true)
@RequestScoped
public class Sidebar {
    @Inject
    private MenuService menuService;
    private List<MenuItem> menuItems;

    public Sidebar() {
        System.out.println("Hello, world!");
    }

    @PostConstruct
    public void init(){
        setMenuItems(menuService.getMainMenu());
    }

    public List<MenuItem> getMenuItems() {
        return menuItems;
    }

    public void setMenuItems(List<MenuItem> menuItems) {
        this.menuItems = menuItems;
    }
}

But! I have value of "title" attribute in my renderer, but not "items"! How to pass "items" attibute value to my component? When I debug, there is no call to "Sidebar" bean. What is wrong in my code?

1 Answers1

0

Object value = menuComponent.getValueExpression("items").getValue(context.getELContext());