代码之家  ›  专栏  ›  技术社区  ›  Wolkenarchitekt

jsf2.0:对selectOneMenu[duplicate]使用枚举值

  •  27
  • Wolkenarchitekt  · 技术社区  · 14 年前

    一个简单的例子:

    // Sample Enum
    public enum Gender {
      MALE("Male"),
      FEMALE("Female");
    
      private final String label;
    
      private Gender(String label) {
        this.label = label;
      }
    
      public String getLabel() {
        return this.label;
      }
    }
    

    <s:convertEnum/> 完成大部分工作的标签。 在Seam中,为了使用枚举的值,我必须编写以下标记(并创建一个提供 #{genderValues}

    <!-- the Seam way -->
    <h:selectOneMenu id="persongender" value="#{person.gender}">
      <s:selectItems var="_gender" value="#{genderValues}"" label="#{_gender.label}"/>
      <s:convertEnum/>
    </h:selectOneMenu>
    

    结果是我不再需要在标记中显式地声明枚举值。 我知道这在JSF中不是很容易<但是JSF2中有什么新功能可以帮助解决这个问题吗?或者焊接有什么帮助吗? 如果在JSF2中没有什么新东西,那么在JSF1.2中最简单的方法是什么?

    或者我甚至可以集成Seam JSF标记和Seam的相应类,以便在JavaEE6应用程序中获得相同的特性(没有Seam容器)?

    5 回复  |  直到 14 年前
        1
  •  48
  •   cheffe    9 年前

    好的,最后一个方法是:

    <converter>
      <converter-for-class>java.lang.Enum</converter-for-class>
      <converter-class>javax.faces.convert.EnumConverter</converter-class>
    </converter>
    

    例如,向托管bean添加一个函数,该函数将枚举值转换为SelectItems数组:

    @ManagedBean
    public class GenderBean {
      public SelectItem[] getGenderValues() {
        SelectItem[] items = new SelectItem[Gender.values().length];
        int i = 0;
        for(Gender g: Gender.values()) {
          items[i++] = new SelectItem(g, g.getLabel());
        }
        return items;
      }
    }
    

    <h:selectOneMenu id="gender" value="#{person.gender}">
      <!-- use property name not method name -->
      <f:selectItems value="#{genderBean.genderValues}" />
    </h:selectOneMenu>
    

        2
  •  21
  •   andand    10 年前

    @ManagedBean
    public class MyManagedBean {
      public Gender[] getGenderValues() {
        return Gender.values;
      }
    }   
    

    在我的标记中

    <h:selectOneMenu id="gender" value="#{person.gender}">
      <f:selectItems value="#{myManagedBean.genderValues}" var="g" 
        itemValue="#{g}" itemLabel="#{g.label}"/>
    </h:selectOneMenu>
    

    现在我得看看 enum 在发送表单时正确保存在我的实体中。我会看看我自己是否能做到这一点-无论如何,我将感谢提示或最佳做法在这方面!

        3
  •  5
  •   Roger Keays    3 年前

    这里有一个更简单的方法,它使用一个简单的getter和setter将字符串封送到枚举。

    https://rogerkeays.com/blog/using-enums-in-el

        4
  •  4
  •   pakore    14 年前

    messages 用于渲染。

    此外,有时您可能希望将枚举呈现为某种唯一标识符,而不是用户可读的文本(用于某些组件内部使用)。

    这是我的转换器:

    import java.util.ResourceBundle;
    
    /*
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements.  See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership.  The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License.  You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied.  See the License for the
     * specific language governing permissions and limitations
     * under the License.
     */
    
    
    
    
    import javax.faces.component.UIComponent;
    import javax.faces.component.UIInput;
    import javax.faces.context.FacesContext;
    import javax.faces.convert.Converter;
    import javax.faces.convert.ConverterException;
    
    import com.eyeprevent.configuration.ConfigurationReader;
    
    
    /**
     * converts an enum in a way that makes the conversion reversible (sometimes)
     * <ul>
     * <li>input: uses its classname and ordinal, reversible<li>
     * <li>else: uses its name, non reversible<li>
     * </ul>
     */
    public class EnumConverter implements Converter
    {
        @SuppressWarnings("unchecked")
        public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException
        {
            if (value == null || value.length() < 1)
            {
                return null;
            }
    
            int pos = value.indexOf('@');
            if (pos < 0)
            {
                throw new IllegalArgumentException(value + " do not point to an enum");
            }
    
            String className = value.substring(0, pos);
            Class clazz;
            int ordinal = Integer.parseInt(value.substring(pos+1), 10);
    
            try
            {
                clazz = Class.forName( className, true, Thread.currentThread().getContextClassLoader() );
                // if the clazz is not an enum it might be an enum which is inherited. In this case try to find the superclass.
                while (clazz != null && !clazz.isEnum())
                {
                    clazz = clazz.getSuperclass();
                }
                if (clazz == null)
                {
                    throw new IllegalArgumentException("class " + className + " couldn't be treated as enum");
                }
    
                Enum[] enums = (Enum[]) clazz.getEnumConstants();
                if (enums.length >= ordinal)
                {
                    return enums[ordinal];
                }
            }
            catch (ClassNotFoundException e1)
            {
                throw new RuntimeException(e1);
            }
    
            throw new IllegalArgumentException("ordinal " + ordinal + " not found in enum " + clazz);
        }
    
        public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException
        {
            if (value == null)
            {
                return "";
            }
    
            Enum<?> e = (Enum<?>) value;
    
            if (component instanceof UIInput || UIInput.COMPONENT_FAMILY.equals(component.getFamily()))
            {
                return e.getClass().getName() + "@" + Integer.toString(e.ordinal(), 10);
            }
            ResourceBundle messages =ConfigurationReader.getMessages(context.getViewRoot().getLocale());
            return messages.getString(e.name());
    
        }
    }
    
        5
  •  2
  •   MTom    10 年前

    我用这个简单的方法,它是相当乐观的,你可以自定义它为自己的目的。我将下面的代码放在一个可重用bean中,可以随时从应用程序调用它,因此您可以使用包中声明的任何枚举。

    public List<String> fromEnum(String cname) {
            List<String> names = new ArrayList<>();
            try {
                Class c = Class.forName(cname);
                Object[] r = c.getEnumConstants();
                if (r != null) {
                    for (Object o : r) {
                        names.add(o.toString());
                    }
                }
            } catch (ClassNotFoundException ex) {
                FaceUtil.ShowError(ex);
            }
            return names;
        }
    public static void ShowError(Exception ex) {
            FacesMessage msg=new FacesMessage(FacesMessage.SEVERITY_ERROR,ex.getMessage(),"Error Message");
            FacesContext.getCurrentInstance().addMessage(null, msg);
            }
    

    <p:selectOneMenu value="#{jobapp.aplicant.marital}">
    <f:selectItems value="#{rtutil.fromEnum('com.company.package.enMarital')}" var="m" itemLabel="#{m}" itemValue="#{m}"/>
    </p:selectOneMenu>