Angular7とBootstrap4を使ってサイトを開発しています。
両者については、なんとなく掴んだ感が出てきていたのですが、性別をラジオボタンで実装するのに、意外と手間取りました。
インターネットを調べてもあまり参考になるものが出てこなかったのですが、こういうのはフロント開発の方にすれば普通のことなんでしょうか。
目指したもの
これでも支障はないんです。でも、今時ってこんな感じの方がかっこいいですよね?
実装してみましょう
かっこいい方を実装するためには、data-toggleというものを使うといいらしいのです。そこで以下のように実装しました。
signin.component.pug
.row
.col-lg-4
p.labeltext 性別
.col-lg-8
.btn-group.btn-group-toggle.form-control(data-toggle="sexbuttons")
label.btn.btn-sm.btn-outline-secondary
input.sr-only(type="radio" name="sex" id="man" autocomplete="off" '[value]'="0" '[(ngModel)]'="model.sex" '#sex'="ngModel" required '(change)'="model.sex=0" '[checked]'="model.sex===0")
| 男性
label.btn.btn-sm.btn-outline-secondary
input.sr-only(type="radio" name="sex" id="woman" autocomplete="off" '[value]'="1" '[(ngModel)]'="model.sex" '#sex'="ngModel" required '(change)'="model.sex=1" '[checked]'="model.sex===1")
| 女性
これだと、かっこいいラジオボタンとしては表示されるのですが、クリックしても黒くなりません。
クリックしたら切り替わる実装
原因は、data-toggleの指定でした。buttonsって決まってるんですね。
signin.component.pug
.row
.col-lg-4
p.labeltext 性別
.col-lg-8
.btn-group.btn-group-toggle.form-control(data-toggle="buttons")
label.btn.btn-sm.btn-outline-secondary
input.sr-only(type="radio" name="sex" id="man" autocomplete="off" '[value]'="0" '[(ngModel)]'="model.sex" '#sex'="ngModel" required '(change)'="model.sex=0" '[checked]'="model.sex===0")
| 男性
label.btn.btn-sm.btn-outline-secondary
input.sr-only(type="radio" name="sex" id="woman" autocomplete="off" '[value]'="1" '[(ngModel)]'="model.sex" '#sex'="ngModel" required '(change)'="model.sex=1" '[checked]'="model.sex===1")
| 女性
クリックした方が黒くなる!よしよし。
双方向データバインディングをしているのですが、クリックした方の値が設定されません。
ラジオボタンとしては完璧なはずだ。本にもそう書いてある。
うーん。
その正体はラベルにあった
かっこいいラジオボタンって、コントロール的にはラジオボタンをクリックしている訳ではないのです。なんとラベルをクリックしていたのです!
ということは、このように実装すれば行けるはず。
signin.component.pug
.row
.col-lg-4
p.labeltext 性別
.col-lg-8
.btn-group.btn-group-toggle.form-control(data-toggle="buttons")
label.btn.btn-sm.btn-outline-secondary('(click)'="model.sex=0" '[class.active]'="model.sex===0")
input.sr-only(type="radio" name="sex" id="man" autocomplete="off" '[value]'="0" '[(ngModel)]'="model.sex" '#sex'="ngModel" required)
| 男性
label.btn.btn-sm.btn-outline-secondary('(click)'="model.sex=1" '[class.active]'="model.sex===1")
input.sr-only(type="radio" name="sex" id="woman" autocomplete="off" '[value]'="1" '[(ngModel)]'="model.sex" '#sex'="ngModel" required)
| 女性
つまりラベルの方のclickイベントで値を設定するのと、値に合わせてactiveクラスを追加するかどうかを決めます。
奥が深い・・・。