1
|
new SelectItem(Title.MISS, "Miss" ); |
Работа с SelectItems до JSF 2.0 часто была утомительной, так как вам нужно было написать код, чтобы адаптировать ваши доменные объекты в SelectItems . JSF 2.0 значительно улучшил ситуацию, и теперь вы можете динамически создавать SelectItems, используя выражения EL. Например:
1
2
3
|
< h:selectOneMenu > < f:selectItems value = "#{customerRepository.all}" var = "customer" label = "#{customer.name}" /> </ h:selectOneMenu > |
Это, безусловно, помогает уменьшить объем кода, но я все еще думаю, что есть вещи, которые мы можем сделать, чтобы сделать SelectItems еще проще, особенно при работе с Spring. Имея это в виду, я разрабатывал компонент <s: selectItems> , предназначенный для замены <f: selectItems> .
Первое, что мы можем сделать, — это помочь уменьшить типизацию, избавляя от необходимости указывать атрибут var . С помощью <s: selectItems> , если атрибут var не указан, он по умолчанию будет item . Таким образом, приведенный выше код может быть написан:
1
2
3
|
< h:selectOneMenu > < s:selectItems value = "#{customerRepository.all}" label = "#{item.name}" /> </ h:selectOneMenu > |
В приведенном выше примере значение привязывается к интерфейсу репозитория, который возвращает коллекцию сущностей Customer . Как и со стандартными компонентами <f: selectItems>, вы также можете привязать к массиву или DataModel . Кроме того, новый компонент также поддерживает любое значение String, разделенное запятыми.
1
2
3
|
< h:selectOneMenu > < s:selectItems value = "Java, Spring, JavaServer Faces" /> </ h:selectOneMenu > |
Следующая вещь, с которой <s: selectItems> может помочь, это нулевые значения. Весьма распространено использовать опцию «Пожалуйста, выберите» в раскрывающихся списках, чтобы представлять нули . В vanilla JSF это часто может означать дополнительную наценку для каждого компонента:
1
2
3
4
|
< h:selectOneMenu > < f:selectItem label = "--- Please Select ---" noSelectionOption = "true" itemValue = "" /> < s:selectItems value = "'{items}" /> </ h:selectOneMenu > |
Вместо того, чтобы нуждаться в этой дополнительной наценке для каждого элемента, наш компонент будет автоматически вставлять опцию «Пожалуйста, выберите» всякий раз, когда он связан с компонентом UISelectOne . Вы можете использовать атрибут includeNoSelectionOption, чтобы переопределить это поведение. Метка, используемая для «опции без выбора», по умолчанию будет «- Пожалуйста, выберите -», но вы можете легко настроить и интернационализировать этот текст, добавив org.springframework.context.MessageSource в ApplicationContext, который может разрешить код «spring.faces». .noselectionoption " .
Что касается объекта MessageSource , компонент <s: selectItems> будет, когда это возможно, пытаться создать метку SelectItem с помощью org.springframework.springfaces.message.ObjectMessageSource . В прошлом я писал о том, как конвертировать объекты в сообщения, и этот компонент просто использует эти идеи.
Новый компонент помог нам при создании элементов SelectItems для отображения, но как насчет обработки отправки формы? Как преобразовать отправленный параметр String обратно в реальный объект ? в приведенном выше примере мы связываемся с сущностями клиента JPA; Значения будут отображаться очень хорошо, но когда вы отправляете форму, отображается «Ошибка преобразования», потому что JSF не знает, как получить обратно отправленную строку в объект Customer . Обычный ответ здесь — разработать собственную реализацию javax.faces.convert.Converter , но это часто проблематично. Часто вы выбираете значение элемента, представляющее собой сложный объект, который трудно представить в виде строки .
Существует интересная техника, которую вы можете использовать при написании конвертера, который будет использоваться с компонентом UISelectOne или UISelectMany . На самом деле вам нужен только код записи для преобразования из Object в String , преобразование в другом направлении может быть выполнено путем итерации SelectItem и возврата единственного значения Object, которое при преобразовании в String соответствует вашему переданному значению. Вы можете прочитать больше об этой идее в этом посте Арджана Тиймса. Использовать эту технику с компонентом <s: selectItems> очень просто, просто предоставьте атрибут itemConverterStringValue, который будет использоваться для создания уникального значения getAsString () :
1
2
3
|
< h:selectOneMenu > < s:selectItems value = "#{customerRepository.all}" label = "#{item.name}" itemConverterStringValue = "#{item.id}" /> </ h:selectOneMenu > |
На самом деле itemConverterStringValue является необязательным. Если вы не укажете его, будет использоваться метод объекта toString () или, в случае JPA @Entity , поле @ID будет использоваться автоматически. Вы по-прежнему можете писать и присоединять свой собственный конвертер, если это необходимо, в таких случаях itemConverterStringValue игнорируется.
Наконец, это еще один трюк, который может выполнить <s: selectItems> . Если вы выберете компонент, связанный с логическим или Enum, то атрибут value может быть полностью опущен. Элементы выбора будут построены на основе всех возможных опций, которые поддерживает привязка («Да» / «Нет» для логических значений или полный набор значений Enum ). Это также работает с типизированными коллекциями. Например, следующее отобразит параметры «Java», «Spring» и «JavaServer Faces» (при условии, что у вас есть соответствующий ObjectMessageSource ):
1
2
3
|
public enum Technology { JAVA, SPRING, JAVASERVER_FACES } |
1
2
3
4
|
public class Bean implements Serializable { private Set<Technology> technologies = new HashSet<Technology>(); // ... getters and setters } |
1
2
3
|
< h:selectManyCheckbox value = "#{bean.technologies}" > < s:selectItems /> </ h:selectManyCheckbox > |
Ссылка: Интеграция Spring & JavaServer Faces: Выберите элементы от нашего партнера JCG Филиппа Уэбба в блоге Фила Уэбба в блоге.