Double-escaped label in SelectOneMenu in PrimeFaces 12

236 Views Asked by At

In PrimeFaces’ SelectOneMenu, I use options (often placeholders) like <please select>, loaded from controller via f:selectItems and escaped automatically by the SelectOneMenu component. After updating PrimeFaces 11 to version 12, the component started to double-escape the characters <, >, & in its label, while the option list is still rendered as expected. (When I click <please select>, the label shows &lt;please select&gt;.)

I tried all combinations of these settings:

  • view: f:selectItems.itemLabelEscaped = "true"/"false"
  • controller: SelectItem.escape = "true"/"false"
  • controller: SelectItem.label is/isn’t escaped manually

The attribute itemLabelEscaped has no effect. Other combinations work as follows:

No. SelectItem.escape SelectItem.label Option in dropdown Shown label in PF 11 Shown label in PF 12
1 false < <i>italics</i> < italics italics italics
2 false &lt; &lt;i&gt;italics&lt;/i&gt; < <i>italics</i> < italics < <i>italics</i>
3 true < <i>italics</i> < <i>italics</i> < <i>italics</i> &lt; &lt;i&gt;italics&lt;/i&gt;
4 true &lt; &lt;i&gt;italics&lt;/i&gt; &lt; &lt;i&gt;italics&lt;/i&gt; &lt; &lt;i&gt;italics&lt;/i&gt; (even more escaped)

In PrimeFaces 11, I used the setting No. 3, and the label was the same as the option in dropdown. After the update, the label gets broken and the only working setting seems to be No. 2, but I don’t want to update all occurrences of selectItems unless necessary.

As I did not find any relevant info in PrimeFaces’ release notes, I would consider it a bug, but I wonder nobody has reported it yet, so I’m not sure: is it a bug, or a feature? This old question seems to be relevant, but how come it worked in PrimeFaces 11?

2

There are 2 best solutions below

3
Jasper de Vries On BEST ANSWER

This is a known and fixed issue. Until PrimeFaces 13 is released, you can MonkeyPatch the workaround.

2
Melloware On

OK it should be fixed for good in PF 13.0 and this MonkeyPatch should solve all your current issues.

if (PrimeFaces.widget.SelectOneMenu) {
    PrimeFaces.widget.SelectOneMenu.prototype.renderSelectItem = function(item, isGrouped) {
        var content = "";
        var $item = $(item);
        var label;
        var title = $item.data("title");
        var escape = $item.data("escape");
        var cssClass;

        if (item.tagName === "OPTGROUP") {
            label = $item.attr("label");
            if (escape) {
                label = $("<div>").text(label).html();
            }
            cssClass = "ui-selectonemenu-item-group ui-corner-all";
        } else { //OPTION
            if (escape) {
                label = $item.html();
                if ($item.text() === "&nbsp;") {
                    label = $item.text();
                }
            } else {
                label = $item.text();
            }
            
            cssClass = "ui-selectonemenu-item ui-selectonemenu-list-item ui-corner-all";
            if (isGrouped) {
                cssClass += " ui-selectonemenu-item-group-children";
            }
        }

        var dataLabel = escape ? label.replaceAll('"', '&quot;') : this.escapeHTMLIfNecessary(label);

        if ($item.data("noselection-option")) {
            cssClass += " ui-noselection-option";
        }

        content += '<li class="' + cssClass + '" tabindex="-1" role="option"';
        if (title) {
            content += ' title="' + title + '"';
        }
        if ($item.is(':disabled')) {
            content += ' disabled';
        }
        content += ' data-label="' + dataLabel + '"';
        content += '>';
        content += label;
        content += '</li>';

        if (item.tagName === "OPTGROUP") {
            content += this.renderSelectItems($item, true);
        }

        return content;
    };

    PrimeFaces.widget.SelectOneMenu.prototype.escapeHTMLIfNecessary = function(value) {
            return String(value).replace(/[<>"'`=\/]/g, function(s) {
                return PrimeFaces.entityMap[s];
            });
     };
}