f: selectOneMenu с параметром

У меня есть набор групп (пользователей) и таблица, где я показываю эти группы (и пользователей). Каждый заголовок таблицы групп включает f:selectOneMenu который позволяет установить значение для всей группы. Для этого примера пусть это будет список значений int (0, 5, 10, 15, 20). Ниже короткой версии вещей

Pojos:

public class User {
    private int    id;
    private String name;
    // .. getter, setter, equals, hashCode
}  

public class Group {
    private int    id;
    private String name;
    // .. getter, setter, equals, hashCode
}

Боб:

@ManagedBean(name = "oneSelectController")
@ViewScoped
public class OneSelectController implements Serializable {

    private List<User>                users;
    private List<Group>               groups;
    private List<Integer>             values;
    private Map<Group, List<User>>    usersToGroup;
    private Map<Group, List<Integer>> valuesToGroup;

    public OneSelectController() {

        log.info("New " + this.getClass().getSimpleName() + " ...");

        users = new ArrayList<>(4);
        users.add(new User(1, "User 1"));
        users.add(new User(2, "User 2"));
        users.add(new User(3, "User 3"));
        users.add(new User(4, "User 4"));

        groups = new ArrayList<>(5);
        groups.add(new Group(1, "Group 1"));
        groups.add(new Group(2, "Group 2"));
        groups.add(new Group(3, "Group 3"));
        groups.add(new Group(4, "Group 4"));
        groups.add(new Group(5, "Group 5"));

        values = Arrays.asList(0, 5, 10, 15, 20);

        usersToGroup = new HashMap<>();
        valuesToGroup = new HashMap<>();

        for (Group g : groups) {
            usersToGroup.put(g, users);
            valuesToGroup.put(g, values);
        }
    }

    public List<Group> getGroups() {
        return groups;
    }

    public List<User> getUsers() {
        return users;
    }

    public Integer getValueByGroup(Group group) {
        // return value for given group
    }

    public List<Integer> getValuesByGroup(Group group) {
        // return list of possible values
    }
}

XHTML:

<p:dataTable id="userTable"
             var="user"
             value="#{oneSelectController.users}">
    <p:column>
        <f:facet name="header">
            <div>User</div>
        </f:facet>
        <div>
            <h:outputText value="#{user.name}"/>
        </div>
    </p:column>
    <p:columns id="groups" value="#{oneSelectController.groups}" var="group">
        <f:facet name="header">
            <div>#{group.name}</div>
            <div>
                <h:selectOneMenu value="#{oneSelectController.getValueByGroup(group)}">
                    <f:selectItems value="#{oneSelectController.getValuesByGroup(group)}" />
                </h:selectOneMenu>
            </div>
        </f:facet>
    </p:columns>
</p:dataTable>

Как настроить рабочий сеттер для h:selectOneMenu? Что бы я ни делал, я получаю исключения. Устроитель (каким-то образом) должен быть способен принять выбранное значение, но также содержать информацию, для какой группы был сделан выбор.

Ответ 1

getValueByGroup не считается получателем JSF, поскольку вы используете его с параметром. Я думаю, что вам лучше всего использовать карту, правильно hashCode() методы hashCode() и equals() для класса Group:

В вашей фасоли:

private Map<Group, Integer> selectedValueByGroup = new HashMap<>();
//Getter

В представлении:

<h:selectOneMenu value="#{oneSelectController.selectedValueByGroup[group]}">
    <f:selectItems value="#{oneSelectController.getValuesByGroup(group)}" />
</h:selectOneMenu>

Кроме того, не связанный с конкретным вопросом, и, как указывает @Kukeltje, вы можете использовать структуру Map для управления значениями, отображаемыми по группам:

В вашей фасоли:

private Map<Group, List<Integer>> valuesByGroup = new HashMap<>();
//Getter

В представлении:

<h:selectOneMenu value="#{oneSelectController.selectedValueByGroup[group]}">
    <f:selectItems value="#{oneSelectController.valuesByGroup[group]}" />
</h:selectOneMenu>

Возможно, вы захотите использовать LinkedHashMap вместо HashMap если для вас важна упорядоченность.

Смотрите также: