Railsでflatpickrを使ってみる

# はじめに
フォームから日付を入力する際、カレンダーから直感的に日付選択できるようにする"datetimepicker"等の日付ピッカー。
その一種であるflatpickrをRailsで使う方法がQiitaに見当たらなかったので記事にしてみました。
なお、当方初学者かつ初投稿なので、間違いなどございましたらご指摘いただけますと幸いです。
### 環境
- ruby 2.6.6
- Rails 5.2.4.4


# flatpickrについて
flatpickrは非常に軽量で導入も簡単です。
flatpickr以外の日付ピッカーとしてbootstrap-datetimepickerが有名ですが、bootstrapやjQueryに依存していたり、bootstrapのバージョンの互換性などなにかと面倒です。
私のような初学者でもポートフォリオへの導入がしやすいかと思います。

### 関連ページ
- [introduction](https://flatpickr.js.org/)<br>
こちらが公式サイトです。(英語サイト)
- [flatpickrドキュメント翻訳](https://tr.you84815.space/flatpickr/index.html)<br>
公式サイトを日本語化してくださっているサイトです。

flatpickrは色々細かく設定できるようなので、上記サイトを御覧ください。

- [flatpickr-rails (github)](https://github.com/zokioki/flatpickr-rails)<br>
Railsで簡単に使えるようgemパッケージ化してくれています。<br>
今回はこちらを使って導入していきます。

# flatpickrインストール
今回は先程のGemを使用するので、Gemfileに以下を記述し、インストールします。

```ruby:gemfile
gem 'flatpickr'
```

```:tarminal
$ bundle install
```
`app/assets/stylesheets/application.css`の拡張子cssをscssに変更
上部にflatpickrを読み込ませる記述を追加します。

```scss:application.scss
/* 
 ...
 ...
// 〜〜〜〜 以下を追加 〜〜〜〜
 *= require flatpickr
// 〜〜〜〜 以上を追加 〜〜〜〜
 */
```
`app/assets/javascripts/application.js`も同様に記述します。
日本語化するのであれば、一緒に`flatpickr/l10n/ja`も導入しましょう。

```js:application.js
//= require rails-ujs
//= require activestorage
// 〜〜〜〜 以下を追加 〜〜〜〜
//= require flatpickr
//= require flatpickr/l10n/ja
// 〜〜〜〜 以上を追加(require turbolinksより上に追加) 〜〜〜〜
//= require turbolinks
//= require_tree 
```
以上でflatpickrの準備は整いました。次は、viewでフォームから実際にflatpickrを表示してみましょう。

# 表示してみる
今回はnewページで、Taskモデルのdate型のaction_atというカラムにデータを入れる場合を想定しましょう。
モデルやカラム名は適宜読み替えて実装してください。

viewではRailsのいつもの感じで`form_with`を使ってフォームを作りましょう。

```erb:views/tasks/new.html.erb
<%= form_with(model: @task, local: true) do |f| %>
  <%= f.text_field :action_at, id: "flatpickr", type: "text", readonly: "" %>
<% end %>
```
`text_field`にわかりやすく`id: "flatpickr"`と記述しました。
idの名前は何でもいいですが、次のjsに書くflatpickrの第一因数と一致させるようにしてください。
また、`readonly:""`でユーザーにflatpickr以外から文字入力をさせないようにしましょう。

続いてJavaScriptの設定に移ります。
新しいjsファイルを作成する場合、ファイル名を`flatpickr.js`にすると`//= require flatpickr`と被って動かなくなるので注意しましょう。
turbolinksを使用していない場合は最初の行は必要ありません。

```js:datetime.js
document.addEventListener('turbolinks:load', () => {
  flatpickr('#flatpickr')
})
```
これでフォームをクリックするとflatpickrが表示されるはずです！
![スクリーンショット 2020-11-30 14.42.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518211/6171aae7-b4a7-f7f3-ef09-2bdb02ab0a6c.png)


# カスタマイズ例
jsでのカスタマイズ例なんかは既にいろいろ記事が上がっていたり、公式サイトにも載っているのですが、少しだけ例を挙げておきます。

#### 日本語化とスマホ対応
```js:datetime.js
document.addEventListener('turbolinks:load', () => {
  // カレンダーの日本語化
  flatpickr.localize(flatpickr.l10ns.ja)
  // カレンダー表示
  flatpickr('#flatpickr', {
    // スマートフォンでもカレンダーに「flatpickr」を使用する設定
    disableMobile: true,
  });
})
```
`//= require flatpickr/l10n/ja`で日本語化を読み込んでいるので、これで曜日などが日本語になります。
![スクリーンショット 2020-11-30 14.43.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518211/e2923119-d010-9234-1406-b75338c4d961.png)


#### 選択可能日を設定
```js:datetime.js
document.addEventListener('turbolinks:load', () => {
  const TODAY = new Date(new Date().setHours(0, 0, 0, 0))

  flatpickr.localize(flatpickr.l10ns.ja)
  flatpickr('#flatpickr', {
    disableMobile: true,
　　//今日までを選択可能にする
    maxDate: TODAY
  });
})
```
今日までを選択可能にしました。`minDate:`とかで一ヶ月前までを選択可能にしたりもできます。
![スクリーンショット 2020-11-30 14.41.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518211/cf6a3ae2-d640-0de1-c288-1a406098cca4.png)
11月28日時点なら、29日、30日と来月以降の文字は選択不可になっています。

### テーマ変更
```scss:application.scss
/* 
 ...
 ...
 *= require flatpickr
 *= require flatpickr/themes/dark.css
 */

```
flatpickrには色々なテーマが用意されており、scssに読み込ませるだけで変更できます。
公式サイト日本語約ページにサンプルがあります。
[Themes](https://tr.you84815.space/flatpickr/themes.html)
![スクリーンショット 2020-11-30 14.45.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518211/448be09b-ec68-6db3-7818-ff0cb658ee20.png)
上の例はdarkテーマを採用していますが、darkのところを他のテーマ名に変えるだけで適用できます。
![スクリーンショット 2020-11-30 14.45.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518211/97e899ec-6cb5-9c5e-13fc-8ec5713a4fdc.png)
**material_blue.css**
![スクリーンショット 2020-11-30 14.46.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518211/cd8bb5c0-1863-f5db-da7a-0188a5f84778.png)
**airbnb**