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

时间:2014-12-12 12:00:55

标签: sorting jsf localization resourcebundle

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

<h:selectOneMenu value="#{bean.selectedKey}">
  <f:selectItems value="#{bean.allKeys}" var="_key" itemLabel="#{msgs[_key]}" />
</h:selectOneMenu>

我的设置使用由faces-config.xml配置的标准资源包,如BalusC所解释的in this answer。上例中的msgs是资源包变量的名称。

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

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

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

1 个答案:

答案 0 :(得分:6)

你基本上有两种选择。

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

    <h:selectOneMenu ... styleClass="ordered">
    
    $("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;
        }
    });
    

  2. 在服务器端排序,您可以在其中创建List<SelectItem>并通过注入抓取#{msgs}。假设您正在使用CDI,因此无法使用@ManagedProperty("#{msgs}"),那么您需要首先为其创建一个生产者。为简单起见,我假设您正在使用OmniFaces(也会根据您的问题历史记录确认)。

    public class BundleProducer {
    
        @Produces
        public PropertyResourceBundle getBundle() {
            return Faces.evaluateExpressionGet("#{msgs}");
        }
    
    }
    

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

    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);
    }
    

    并在没有var的情况下直接引用它,如下所示:

    <f:selectItems value="#{bean.allKeys}" />