Django、カスタムチェックボックスの作成

Python Django Djangoカスタムウィジェット HTML・CSS

カスタムチェックボックスとは

今回、次のようなものを作ります。

カスタムチェックボックス

これは、チェックボックスをカスタマイズして作っています。チェックボックスは、通常は次のようなものですね。これをCSSとかで、上のようにしました。

普通のチェックボックス

こういう見た目のものを作るだけならば、チェックボックスを使わなくても実装はできます。しかし、複数選択に対応したい場合だったり、他のフォーム部品との兼ね合い・・・例えばタグの他にキーワード検索も一緒にさせたいとか、そういったことになってくると、チェックボックスで実装するのが楽ちんです。

GithubにDjangoプロジェクトを置いているので、興味のある方は試してください。

チェックボックスのカスタマイズ方法

やり方は幾つかあるようなのですが、よく見かける、情報量の多い方法は隣接セレクタを使う方法があります。

ステップ1

まず、次のようにHTMLを書きます。

<input type="checkbox" name="tags" value="1" id="id_tags_0">
<label for="id_tags_0">Python</label>

この段階では、ただのチェックボックス。<input type="checkbox"は四角いチェック部分で、<labelはPythonという文字部分です。

ただのチェックボックス

ステップ2

四角いチェックボックス部分を、display:noneで隠します。

<style>
    input[type="checkbox"] {
        display: none;
    }
</style>
<input type="checkbox" name="tags" value="1" id="id_tags_0">
<label for="id_tags_0">Python</label>

チェック部分が消えて、Pythonという文字だけ、つまりlabel要素だけ表示されるようになりました。

labelだけ見える

ステップ3

label要素に対して、おしゃれなCSSを設定します。

<style>
    input[type="checkbox"] {
        display: none;
    }

     label {
        display: inline-block;
        border-radius: 20px;
        text-align: center;
        text-decoration: none;
        border: solid 1px #ccc;
        transition: 0.25s;
        padding: 6px 18px;
        cursor: pointer;
        font-size: 14px;
        margin: 3px;
    }
</style>
<input type="checkbox" name="tags" value="1" id="id_tags_0">
<label for="id_tags_0">Python</label>

すると、それっぽい見た目になってきましたね。チェックボックスに紐づいたラベル(labelのforにチェックボックスのidを指定したもの)は、クリックするとチェックボックスにクリックしたことを伝えてくれます。なので、このラベルをクリックするだけで、内部的にはチェックボックスにチェックが入ってるのです。非表示にしているので、それが見えないのですが。

それっぽい見た目

ステップ4

チェックボックスにチェックが入っているときに、見た目的にそれを教える必要があります。ここでよく使われるのが隣接セレクタです。

<style>
    input[type="checkbox"] {
        display: none;
    }

    label {
        display: inline-block;
        border-radius: 20px;
        text-align: center;
        text-decoration: none;
        border: solid 1px #ccc;
        transition: 0.25s;
        padding: 6px 18px;
        cursor: pointer;
        font-size: 14px;
        margin: 3px;
    }

    input[type="checkbox"]:checked + label {
        background: #00809d;
        color: #fff;
    }
</style>
<input type="checkbox" name="tags" value="1" id="id_tags_0">
<label for="id_tags_0">Python</label>

増えたのは、input[type="checkbox"]:checked + labelという指定です。これはチェックが入ったチェックボックスすぐ後にあるラベルという意味になります。上に書いたように、ラベル部分をクリックでそのチェックボックスにチェックが入ってくれます。チェックボックスすぐ後にあるラベルというのは、クリックしたラベルのことなので、これでクリックしたときに色がついて分るようになります。

クリックしたときに色が

Djangoデフォルトのチェックボックス

Djangoが作るデフォルトのチェックボックスのHTMLについて知っておく必要があります。これは次のようなHTMLになります。

<ul id="id_tags">
    <li>
        <label for="id_tags_0">
            <input type="checkbox" name="tags" value="1" id="id_tags_0" checked>
             Python
        </label>
    </li>
</ul>

ulやliは問題ないのですが、上の隣接セレクタの方法を使うに当たっては、このHTMLだとちょっと難しそうです。なので、もう少しシンプルなHTMLを生成するウィジェットを作ってみましょう。

シンプルなチェックボックスウィジェット作成

カスタムウィジェットは、もう何度かブログでやってきました。専用のタグもつけているので、興味がある方は他の記事も見てみてください。

アプリケーション内にでも、widgets.pyといった分かりやすい名前のファイルを作ります。そして、次のように書きます。

from django import forms


class CustomCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
    template_name = 'app/widgets/custom_checkbox.html'
    option_template_name = 'app/widgets/custom_checkbox_option.html'

    def __init__(self, attrs=None):
        super().__init__(attrs)
        if 'class' in self.attrs:
            self.attrs['class'] += ' custom-checkbox'
        else:
            self.attrs['class'] = 'custom-checkbox'

チェックボックスにはcustom-checkboxというcssのclassを持たせて、HTMLを作るテンプレートを別に指定しています。

app/widgets/custom_checkbox.htmlを作ります。

{% for group, options, index in widget.optgroups %}{% for option in options %}{% include option.template_name with widget=option %}{% endfor %}{% endfor %}

これは、もともともチェックボックスが使うテンプレートと殆ど同じです。ulとかliを作らないように、少しコードを削除しただけです。

app/widgets/custom_checkbox_option.htmlを作ります。

{% include "django/forms/widgets/input.html" %}<label for="{{ widget.attrs.id }}" class="custom-checkbox-label">{{ widget.label }}</label>

これが、inputの横にlabelを配置するようにしています。そして、labelのclassにはcustom-checkbox-labelという指定もしています。

後は、このウィジェットを使うだけです。例えば、フォームで次のように指定します。

from django import forms
from .models import Tag
from .widgets import CustomCheckboxSelectMultiple


class SampleForm(forms.Form):
    tags = forms.ModelMultipleChoiceField(
        label='タグ', queryset=Tag.objects, required=False,
        widget=CustomCheckboxSelectMultiple,  # ここで、今作ったウィジェットを指定
    )

最後に、CSSを設定しておきましょう。これで、最初に紹介したような見た目になります。

        /* カスタムチェックボックス */
        .custom-checkbox {
            display: none;
        }

        .custom-checkbox:checked + .custom-checkbox-label {
            background: #00809d;
            color: #fff;
        }

        .custom-checkbox-label {
            display: inline-block;
            border-radius: 20px;
            text-align: center;
            text-decoration: none;
            border: solid 1px #ccc;
            transition: 0.25s;
            padding: 6px 18px;
            cursor: pointer;
            font-size: 14px;
            margin: 3px;
        }

        .custom-checkbox-label:hover {
            opacity: 0.5;
        }

Relation Posts

関連記事はありません。

Comment

記事にコメントする

まだコメントはありません。