🎻

Select2でoptionタグのラベルにHTMLを使う方法

2020/07/28に公開

こんな感じでSelect2のoptionタグのラベルにHTMLを使う方法です。

パターン1:選択肢をJavaScript側に書く場合

Select2の配列データソース機能 を使って、JavaScript側に選択肢の情報を書きつつ、escapeMarkup オプションを使ってエスケープを回避します。

<select id="target"></select>
$('#target').select2({
  data: [
    {id: 1, text: 'ほげほげ <span class="badge badge-warning">タイプA</span>'},
    {id: 2, text: 'ふがふが <span class="badge badge-success">タイプB</span>'},
    {id: 3, text: 'ぴよぴよ <span class="badge badge-warning">タイプA</span>'},
  ],
  escapeMarkup: function(markup) {
    return markup;
  },
});

参考:jquery - How to render html in select2 options - Stack Overflow

パターン2:ラベル部分の文字列をHTMLエスケープしておく場合

配列データソースを使わず、HTMLに直接optionタグを書きたい場合は、ラベル部分の文字列をHTMLエスケープしておく必要があります。そうしないと、 escapeMarkup に来た時点ですでにタグが完全にサニタイズされてしまっていて何も手出しできません。

例えばPHPの Twig というテンプレートエンジンを使う場合、以下のようなコードで実現できます。

<select id="target">
  <option value="1">ほげほげ {{ '<span class="badge badge-warning">タイプA</span>'|escape }}</option>
  <option value="2">ふがふが {{ '<span class="badge badge-success">タイプB</span>'|escape }}</option>
  <option value="3">ぴよぴよ {{ '<span class="badge badge-warning">タイプA</span>'|escape }}</option>
</select>
$('#target').select2({
  escapeMarkup: function(markup) {
    return markup;
  },
});

おまけ:SymfonyのFormTypeと併用する例

おまけです。Symfony のFormTypeと併用する場合の例を示します。

class FooType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('bar', EntityType::class, [
                'class' => Bar::class,
                'choice_label' => function (Bar $choice, $key, $value) {
                    $label = $choice->getName();
                    $label .= $choice->getType() === 'A' ? '<span class="badge badge-warning">タイプA</span>' : '<span class="badge badge-success">タイプB</span>';
                    return $label;
                },
            ])
        ;
    }
}

こんな感じで、EntityTypechoice_label オプション を使ってラベルを書きます。

EntityType でなくても、 ChoiceType の派生ならなんでも使えます✋

この場合、ラベル部分のHTML文字列はSymfonyが勝手にエスケープしてくれるので、特に何もせずそのまま escapeMarkup が使えます👍

$('#foo_bar').select2({
  escapeMarkup: function(markup) {
    return markup;
  },
});
GitHubで編集を提案

Discussion