如何对将在JSF输出中本地化的列表进行排序

Mar*_*ler 4 sorting jsf localization resourcebundle

在我的应用程序中,我有一个键(字符串)列表,用户可以在其中选择其中一个.在用户界面中,将根据当前区域设置输出密钥:

<h:selectOneMenu value="#{bean.selectedKey}">
  <f:selectItems value="#{bean.allKeys}" var="_key" itemLabel="#{msgs[_key]}" />
</h:selectOneMenu>
Run Code Online (Sandbox Code Playgroud)

我的设置使用配置的标准资源包,faces-config.xml如BalusC 在本回答中所述.msgs在上面的示例中是资源包变量的名称.

我现在selectOneMenu想要的是,要按字母顺序排序的项目.当然,顺序取决于使用的区域设置.问题是,我不能/不会在backing-bean中进行排序,因为我不知道JSF页面将如何输出密钥.

这个问题对我来说似乎很通用,所以我想知道解决这类问题的最佳做法是什么.

(当然问题不仅适用于selectOneMenu.任何将在用户界面中输出的列表/集合都会遇到同样的问题.)

Bal*_*usC 6

你基本上有2个选择.

  1. 在JS的一点帮助下在客户端排序.我简单地假设您正在使用jQuery.

    <h:selectOneMenu ... styleClass="ordered">
    
    Run Code Online (Sandbox Code Playgroud)
    $("select.ordered").each(function(index, select) {
        var $select = $(select);
        $select.find("option").sort(function(left, right) {
            return left.text == right.text ? 0 : left.text < right.text ? -1 : 1;
        }).appendTo($select);
        if (!$select.find("option[selected]").length) {
            select.options.selectedIndex = 0;
        }
    });
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在服务器端排序,您可以通过注入创建List<SelectItem>和抓取#{msgs}.假设您正在使用CDI而无法使用@ManagedProperty("#{msgs}"),则需要首先为其创建一个生产者.为简单起见,我假设您使用的是OmniFaces(根据您的问题历史记录确认).

    public class BundleProducer {
    
        @Produces
        public PropertyResourceBundle getBundle() {
            return Faces.evaluateExpressionGet("#{msgs}");
        }
    
    }
    
    Run Code Online (Sandbox Code Playgroud)

    然后你可以在与以下相关联的支持bean中使用它,如下所示<f:selectItems value>:

    private static final Comparator<SelectItem> SORT_SELECTITEM_BY_LABEL = new Comparator<SelectItem>() {
        @Override
        public int compare(SelectItem left, SelectItem right) {
            return left.getLabel().compareTo(right.getLabel());
        }
    };
    
    private List<SelectItem> allKeys;
    
    @Inject
    private PropertyResourceBundle msgs;
    
    @PostConstruct
    public void init() {
        allKeys = new ArrayList<>();
    
        for (String key : keys) {
           allKeys.add(new SelectItem(key, msgs.getString(key)));
        }
    
        Collections.sort(allKeys, SORT_SELECTITEM_BY_LABEL);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    并直接引用它,不var作如下:

    <f:selectItems value="#{bean.allKeys}" />
    
    Run Code Online (Sandbox Code Playgroud)