Aritz
Aritz

Reputation: 31651

PickList with large set of elements slows down in Google Chrome

I'm dealing with an issue in the last version of Primefaces community (5.1). Using it with JSF 2.1.29 and +1000 elements brings a terrible performance issue when using Google Chrome 38 browser, either in view loading and element transfer. I'm afraid it's all about a problem in Chrome's Javascript engine. Here you've got a very basic use case:

@ManagedBean
@ViewScoped
public class PickListTestBean implements Serializable {

    private DualListModel<String> values;

    public PickListTestBean() {
        List<String> source = new ArrayList<String>();
        List<String> target = new ArrayList<String>();
        for (int i = 0; i < 1000; i++) {
            source.add("value" + i);
        }
        values = new DualListModel<String>(source, target);
    }

    public DualListModel<String> getValues() {
        return values;
    }

    public void setValues(DualListModel<String> values) {
        this.values = values;
    }

}

And the view:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:p="http://primefaces.org/ui"
    xmlns:ui="http://java.sun.com/jsf/facelets">
    <h:head />
    <h:body>
        <h:form>
            <p:pickList value="#{pickListTestBean.values}" var="val" 
                effect="none" itemValue="#{val}" itemLabel="#{val}" 
                showSourceFilter="true" showTargetFilter="true">
                <p:column>
                    #{val}
                </p:column>
            </p:pickList>
        </h:form>
    </h:body>
</html>

That's properly working in FF and IE latest versions...

Upvotes: 1

Views: 976

Answers (2)

Aritz
Aritz

Reputation: 31651

Seems to be a Primefaces issue, which I opened a ticket for, but they said they were not going to fix it since there are too many elements for the component (which is true). However, there is a way to make it more efficient. The function for item generation loops appending the HTML content directly over the DOM:

generateItems: function(list, input) {   
    list.children('.ui-picklist-item').each(function() {
        var item = $(this),
        itemValue = PrimeFaces.escapeHTML(item.attr('data-item-value')),
        itemLabel = item.attr('data-item-label'),
        escapedItemLabel = (itemLabel) ? PrimeFaces.escapeHTML(itemLabel) : '';

        input.append('<option value="' + itemValue + '" selected="selected">' + escapedItemLabel + '</option>');
    });
}

Overriding the generateItems function for the PickList improves the perfomance noticeably:

<script>
    PrimeFaces.widget.PickList.prototype.generateItems = function(b, a) {
        var output = '';
        b.children(".ui-picklist-item").each(function () {
            var e = $(this),
            f = PrimeFaces.escapeHTML(e.attr("data-item-value")),
            d = e.attr("data-item-label"),
            c = (d) ? PrimeFaces.escapeHTML(d) : "";
            output += '<option value="' + f + '" selected="selected">' + c + "</option>";
        })
        a.append(output)
    }
</script>

Upvotes: 1

Neubaut
Neubaut

Reputation: 1

A slight alteration to the above answer. In case you're only interested in the target selection and would like to use a large input as source you might want to use the following:

PrimeFaces.widget.PickList.prototype.generateItems = function(b, a) {
    var output = '';
    if(b === this.targetList) {
        b.children(".ui-picklist-item").each(function () {
            var e = $(this),
            f = PrimeFaces.escapeHTML(e.attr("data-item-value")),
            d = e.attr("data-item-label"),
            c = (d) ? PrimeFaces.escapeHTML(d) : "";
            output += ('<option value="' + f + '" selected="selected">' + c + '</option>');
        });
    }
    a.append(output);
};

This will make sure processing is only performed on the (smaller) target list. As a result the DualListModel will return zero elements in the source while returning the selection as target.

Upvotes: 0

Related Questions