F: selectItems, показывающий класс не значение

Я новичок в facelets, и я создал проект с использованием netbeans, но я боюсь с тегом.

У меня

<h:selectOneMenu id="country" value="#{organisation.organisation.country}" title="Country" >
                <f:selectItems value="#{country.countryItemsAvailableSelectOne}"/>
            </h:selectOneMenu>

В элементе select я получаю classpath.Country [iso = GB], который я вижу, является объектом, но я действительно хочу увидеть значение country.prinableName. Я посмотрел на это полдня и набрал пустой Спасибо за любую помощь

Ответ 1

Поскольку вы говорите о Facelets, я буду считать JSF 2.x.

Для начала HTML - это одна и вся строка. JSF генерирует HTML. По умолчанию объекты String Java не соответствуют String методом toString(), преобразованным в их представление String, в то время как JSF генерирует HTML. Чтобы правильно преобразовать эти объекты Java и String, вам понадобится Converter.

Я предполагаю, что ваш объект Country уже имеет метод equals() правильно реализован, иначе проверка позже завершится с ошибкой проверки: значение недействительно, потому что выбранный объект не возвращает true при тестировании equals() для любого из доступных элементов.

Я также сделаю небольшое изменение в названии, так как #{country} является запутанным управляемым именем bean, потому что он, по-видимому, не представляет экземпляр класса Country. Я назову его Data, который должен содержать данные расширенного приложения.

@ManagedBean
@ApplicaitionScoped
public class Data {

    private static final List<Country> COUNTRIES = populateItSomehow();

    public List<Country> getCountries() {
        return COUNTRIES;
    }

    // ...
}

Я предполагаю, что класс Country имеет два свойства code и name. Я предполагаю, что управляемый bean, который получает выбранную страну, имеет свойство private Country country. В <f:selectItems> вам нужно выполнить цикл над #{data.countries} и указать объект страны как значение объекта и название страны как метку элемента.

<h:selectOneMenu value="#{bean.country}">
    <f:selectItems value="#{data.countries}" var="country" itemValue="#{country}" itemLabel="#{country.name}" />
</h:selectOneMenu>

Теперь вам нужно создать Converter для класса Country. Мы перейдем на основе кода страны, который уникален для каждой страны (правда?). В getAsString() вы реализуете код, который преобразует объект Java в его уникальное строковое представление, которое должно использоваться в HTML. В getAsObject() вы реализуете код, который преобразует уникальное представление HTML String обратно в объект Java.

@FacesConverter(forClass=Country.class)
public class CountryConverter implements Converter {

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        return (value instanceof Country) ? ((Country) value).getCode() : null;
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value == null) {
            return null;
        }

        Data data = context.getApplication().evaluateExpressionGet(context, "#{data}", Data.class);

        for (Country country : data.getCountries()) {
            if (country.getCode().equals(value)) {
                return country;
            }
        }

        throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to Country", value)));
    }

}

@FacesConverter автоматически зарегистрирует его в JSF, и JSF будет автоматически использовать его всякий раз, когда он встречает выражение типа Country. В конечном итоге вы получаете код страны как значение позиции и название страны в качестве метки элемента. JSF преобразует представленный код страны обратно в полнофункциональный объект Country после отправки формы.

В JSF 1.x принцип не сильно отличается. В этом блоге вы можете найти два основных примера запуска: Объекты в h:selectOneMenu.

Ответ 2

Что случилось с вами, selectOneMenu вызывать toString() для всех заданных объектов.

Вы должны использовать selectitems или просто converter, чтобы управлять этим. Очень простой пример:

price.xhtml:

<h:selectOneMenu id="priceMenu" value="#{priceBean.selectedPrice}">
    <f:selectItems value="#{priceBean.prices}" />
</h:selectOneMenu>

PriceBean.java:

..
private String selectedPrice;
..
public String getSelectedPrice() {
    return selectedPrice;
}

public void setSelectedPrice(String newPrice) {
    selectedPrice = newPrice;
}
..
public List<SelectItem> getPrices() {
    List<SelectItem> retVal = new ArrayList<SelectItem>();

    retVal.add(new SelectItem("2"));
    retVal.add(new SelectItem("4"));
    retVal.add(new SelectItem("6"));

    return retVal;
}

Дополнительная информация о SelectItem. Если вы хотите напрямую использовать специальный объект, например объект с именем Price, вам нужно использовать конвертер. Здесь показан пример и здесь.

Ответ 3

Если вы добавите editable="true" в свой

<h:selectOneMenu value="#{bean.country}">

Затем вы получите неожиданное значение String (не от getAsString()) в методе конвертера:

public Object getAsObject(FacesContext context, UIComponent component, String value) { }