Aurelia で Date Range Picker を使う

公開日:2018-10-15
最終更新:2018-10-24
※この記事は外部サイト(https://qiita.com/hayato-yamashita/items/4...)からのクロス投稿です

今回は Aurelia で Date Range Picker を使う方法について書いていきます。

最終的に、下図の「Expiry Period」のようになります。
日付を範囲選択したい場合に便利ですので、宜しければご覧ください。

また、解説不要な人のために GitHub リポジトリの URL を載せておきますね。

https://github.com/hayato-yamashita/aurelia-daterangepicker

該当のコミットはこちら。

https://github.com/hayato-yamashita/aurelia-daterangepicker/commit/23643928914ce9e98958e04f5ec20c5907092b74

Date Range Picker とは

A JavaScript component for choosing date ranges, dates and times.

jQueryMoment.js に依存する日付範囲選択のためのツールですね。時刻も含めて選べます。
動くサンプルは Examples に載っているので、イメージを掴みやすいです。

TL;DR

  • 日付の範囲選択を Datepicker でゴニョゴニョするのが疲れた人は Date Range Picker がオススメだよ
  • Aurelia でどう使うのか、導入する手順を書いたよ

対象読者

Aurelia で Date Range Picker を使おうと考えている人。

前提環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion:    10.11.6
BuildVersion:    15G22010
$ yarn -v
1.7.0

導入するもの

事前準備

Aurelia - Contact Manager Tutorial を済ませておいてください。
前はチュートリアルなかった気がしたんですけど、少し見ない間にどんどん変わっていきますね。
さすが 未来志向フレームワーク

今回はそちらに「有効期限」を追加する形で実装していきます。

Tutorial をやるのが面倒な人は、以下で引っ張ってきても良いです。
Date Range Picker を導入する直前の状況を再現できます。

$ git clone [email protected]:hayato-yamashita/aurelia-daterangepicker.git
$ cd aurelia-daterangepicker
$ git checkout 47e25155d22943a373266bd9ce79b021a1c8eae4

導入手順

1. Date Range Picker をインストール

npm で管理されているので、インストールは楽ちんです。
私は yarn を使っているので以下のコマンドです。npm の人は適宜読み替えてください。

$ yarn add daterangepicker

2. Date Range Picker を扱う Custom Element を作成

src 配下に、以下の3ファイルを作成してください。

  • date-range-picker.html
  • date-range-picker.js
  • date-range-picker.css

以降、それぞれに記載する内容と解説を書いていきます。

src/date-range-picker.html

必要な css を読み込んで、側を作るだけなので、そこまで難しくないです。

.form-control クラスを設定しているので Bootstrap の Form controls に則ることができるようにしてあります。
.input-group クラスなども適用できるってことですね。

<template class="form-control">
  <require from='daterangepicker/daterangepicker.css'></require>
  <require from='./date-range-picker.css'></require>

  <div class="date-range-picker">
    <span class="date-range">
      <time datetime="${startDate}">${startDate}</time>
      <span>-</span>
      <time datetime="${endDate}">${endDate}</time>
    </span>
  </div>
</template>

src/date-range-picker.js

いくつかのブロックに分けて解説するので、先に完成形を書いておきます。

import { inject, bindable, bindingMode } from 'aurelia-framework';
import $ from 'jquery';
import moment from 'moment';
import 'daterangepicker';

@inject(Element)
export class DateRangePicker {
  @bindable({defaultBindingMode: bindingMode.twoWay}) startDate;
  @bindable({defaultBindingMode: bindingMode.twoWay}) endDate;
  @bindable({defaultBindingMode: bindingMode.oneTime}) options;

  constructor(element) {
    this.element = element;
  }

  created(owningView) {
    this.owningView = owningView;
  }

  attached() {
    this.options = $.extend(true, {
      locale: {
        format: moment.HTML5_FMT.DATE
      }
    }, this.options);

    this.options = $.extend(this.options, {
      startDate: moment(this.startDate, this.options.locale.format),
      endDate: moment(this.endDate, this.options.locale.format)
    });

    $(this.element).daterangepicker(this.options, (start, end) => this.apply(start, end));
  }

  apply(startDate, endDate) {
    this.startDate = startDate.format(this.options.locale.format);
    this.endDate = endDate.format(this.options.locale.format);
  }

  startDateChanged(newValue) {
    if (this.owningView.isAttached) {
      $(this.element).data('daterangepicker').setStartDate(newValue);
    }
  }

  endDateChanged(newValue) {
    if (this.owningView.isAttached) {
      $(this.element).data('daterangepicker').setEndDate(newValue);
    }
  }
}

まずは import 部分。
使用する jQuery, Moment.js を読み込み、Date Range Picker を読み込ませて jQuery に Mixin しています。

import { inject, bindable, bindingMode } from 'aurelia-framework';
import $ from 'jquery';
import moment from 'moment';
import 'daterangepicker';

次に宣言。
startDateendDate は双方向バインドする必要があるので bindingMode.twoWay を指定。
options は Date Range Picker のオプションを利用側から扱えるようにしています。オプションの詳細は Options で。

@inject(Element)
export class DateRangePicker {
  @bindable({defaultBindingMode: bindingMode.twoWay}) startDate;
  @bindable({defaultBindingMode: bindingMode.twoWay}) endDate;
  @bindable({defaultBindingMode: bindingMode.oneTime}) options;

次にコンストラクタとか。
element は Date Range Picker を使うために必要です。jQuery Plugin を使う場合によく見ますね。
owningViewstartDateendDate の変更監視メソッド内で attached 後かどうかを判定するために使います。

  constructor(element) {
    this.element = element;
  }

  created(owningView) {
    this.owningView = owningView;
  }

次に attached です。

$.extend(true, {/* default */}, {/* override */}) の形で書いていますので、bind された options の値を優先させます。
また、startDateendDate は twoWay bind で渡された値を優先させています。

options の設定が終わったら、Date Range Picker の初期化。
値が反映された時のメソッドは apply(start, end) で定義してあります。

また、moment.HTML5_FMT.DATESpecial Formats を参考にしています。

  attached() {
    this.options = $.extend(true, {
      locale: {
        format: moment.HTML5_FMT.DATE
      }
    }, this.options);

    this.options = $.extend(this.options, {
      startDate: moment(this.startDate, this.options.locale.format),
      endDate: moment(this.endDate, this.options.locale.format)
    });

    $(this.element).daterangepicker(this.options, (start, end) => this.apply(start, end));
  }

次に Date Range Picker の反映処理。
引数で渡ってくる値は Moment.js のインスタンスになっていますので、これを文字列に変換しています。
twoWay bind している startDateendDate に設定しているので、この Custom Element の利用側の変数にも反映されます。

  apply(startDate, endDate) {
    this.startDate = startDate.format(this.options.locale.format);
    this.endDate = endDate.format(this.options.locale.format);
  }

最後に startDateendDate の変更検知メソッド。
Aurelia では Observable Properties を使って変数の変更検知を行うことができますが、bind される変数も使えます。
ここでは、この Custom Element 外から値を変更された場合に Date Range Picker の選択範囲に反映されるようにしています。

ちょっと特殊なのは if (this.owningView.isAttached) ですね。
$(this.element).data('daterangepicker') は attached されていないと存在しないため、この判定を行っています。

  startDateChanged(newValue) {
    if (this.owningView.isAttached) {
      $(this.element).data('daterangepicker').setStartDate(newValue);
    }
  }

  endDateChanged(newValue) {
    if (this.owningView.isAttached) {
      $(this.element).data('daterangepicker').setEndDate(newValue);
    }
  }

src/date-range-picker.css

最後にスタイルの設定です。
flexbox を使ったり、擬似クラスの before/after を使ったりしています。
あと、チュートリアルで組み込まれていた Font Awesome も使っています。

.date-range-picker {
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.date-range-picker::before {
  font-family: FontAwesome;
  content: '\f073';
  padding-right: .5rem;
  flex: 0 0 auto;
}
.date-range-picker::after {
  font-family: FontAwesome;
  content: '\f0d7';
  padding-left: .5rem;
  flex: 0 0 auto;
}

.date-range-picker .date-range {
  flex: 1 1 auto;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

3. 作成した Custom Element を使う

いよいよ Contact で「有効期限」を扱える手順です。

Contact Manager では WebApi に初期データが作られているので、これに有効期限の from と to を追加します。

let contacts = [
  {
    id: getId(),
    firstName: 'John',
    lastName: 'Tolkien',
    email: '[email protected]',
    phoneNumber: '867-5309',
    expiryFrom: '2017-01-01',
    expiryTo: '2019-01-01'
  },
  {
    id: getId(),
    firstName: 'Clive',
    lastName: 'Lewis',
    email: '[email protected]',
    phoneNumber: '867-5309',
    expiryFrom: '2017-01-01',
    expiryTo: '2019-01-01'
  },
  {
    id: getId(),
    firstName: 'Owen',
    lastName: 'Barfield',
    email: '[email protected]',
    phoneNumber: '867-5309',
    expiryFrom: '2017-01-01',
    expiryTo: '2019-01-01'
  },
  {
    id: getId(),
    firstName: 'Charles',
    lastName: 'Williams',
    email: '[email protected]',
    phoneNumber: '867-5309',
    expiryFrom: '2017-01-01',
    expiryTo: '2019-01-01'
  },
  {
    id: getId(),
    firstName: 'Roger',
    lastName: 'Green',
    email: '[email protected]',
    phoneNumber: '867-5309',
    expiryFrom: '2017-01-01',
    expiryTo: '2019-01-01'
  }
];

そしたら、ContactDetail で扱えるようにします。

<template>
  <require from="./date-range-picker"></require>

<!-- 中略 -->

        <div class="form-group row">
          <label class="col-sm-3 col-form-label">Expiry Period</label>
          <div class="col-sm-9">
            <date-range-picker start-date.bind="contact.expiryFrom" end-date.bind="contact.expiryTo"></date-range-picker>
          </div>
        </div>

4. au run する

これで準備完了です。

Aurelia を起動すれば、「有効期限」が追加され、Date Range Picker で扱えるようになっています。

$ au run

もし、上記で起動できなければ au run --watch を試してください。

http://localhost:3000/ にアクセスすると、以下のようになっているはずです。

これで完了です。お疲れ様でした。

おわりに

これで Aurelia で Date Range Picker を扱えるようになりました。
これがあれば Datepicker を2つ使ったまどろっこしい日付範囲選択から脱却できますね。

もし Date Range Picker を日本語化したい場合は、以下の記事を参考にすると良いと思います。
コピペで動く。bootstrap-daterangepickerの導入と日本語化

それでは、良い Aurelia 生活を。

記事が少しでもいいなと思ったらクラップを送ってみよう!
18
+1
@phayacellの技術ブログ

よく一緒に読まれている記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる

技術ブログをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

技術ブログを開設する

Qrunchでアウトプットをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

Markdownで書ける

ログ機能でアウトプットを加速

デザインのカスタマイズが可能

技術ブログ開設

ここから先はアカウント(ブログ)開設が必要です

英数字4文字以上
.qrunch.io
英数字6文字以上
ログインする