[祝GA] lightning:input の DatePicker は入力可能な日を制限できる という投稿をしておきながら、「お前は何を言ってるんだ?」という気がしなくもないですが、気付いてしまったのでメモしておきます
TL;DR
- どんな場合?
- Datepicker と他のフォーム (例えば SUBMIT ボタン) があるような場合
- Datepicker にテキスト入力して SUBMIT すると、範囲外の日付を入力できてしまう (下の gif 参照)
- 回避方法?
- controller.js or helper.js で validation かなと
以下、時間がある人向け
どんな場合?
以下の gif を見ていただくと早いかと思いますが、Datepicker の入力範囲外 (グレーアウト) の 7/25 という値は、キーボード入力できてしまうのですね。。。
「範囲外は入力できないはず」と安心しきって SUBMIT ボタンのハンドラでバリデーションをかけていないと、範囲外の値が流れていってしまうことになります
ちなみに、ソースは以下です。
<!-- コンポーネント -->
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes">
<!-- body -->
<div class="row">
<h2 class="header">Datepicker</h2>
<lightning:input type="date" aura:id="datepicker1" name="input1"
label="Date field with min and max values"
value="2018-07-10" min="2018-07-05" max="2018-07-20" />
<!-- SUBMIT ボタン -->
<div class="gutter"/>
<lightning:button variant="brand" label="SUBMIT" onclick="{! c.handleClick }"/>
<!-- SUBMIT ボタンクリックで日付を表示する -->
<div class="gutter"/>
<div aura:id="msg">
You entered: <ui:outputDate aura:id="oDate" value="" />
</div>
</div>
</aura:component>
// controller.js
({
handleClick: function(cmp, event, helper) {
// Datepicker の日付を取得して
const value = cmp.find("datepicker1").get("v.value");
// outputDate にセットする
cmp.find("oDate").set("v.value", value);
}
})
// style.css
.THIS {
background-color: white;
margin: 5rem;
height: 25rem;
padding: 2rem;
}
.THIS .gutter {
margin-top: 2rem;
}
回避方法
lightning:inpu type="date"
の属性でそれらしいものが見つからなかったので、地道にハンドラ (controller.js or helper.js) 内で validation が手っ取り早いかなと思います。
日付については moment.js (v2.22.2) のお世話になります。moment.min.js 16.4k
を右クリックで保存して、静的リソースに momentjs
のように入れました。
挙動はシンプルに「max を超えている場合は何もしない」ことにしました。
<!-- コンポーネント -->
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes">
<!-- lib -->
<ltng:require scripts="{!$Resource.momentjs}" />
<!-- body -->
<div class="row">
<h2 class="header">Datepicker</h2>
<lightning:input type="date" aura:id="datepicker1" name="input1"
label="Date field with min and max values"
value="2018-07-10" min="2018-07-05" max="2018-07-20" />
<!-- SUBMIT ボタン -->
<div class="gutter"/>
<lightning:button variant="brand" label="SUBMIT" onclick="{! c.handleClick }"/>
<!-- SUBMIT ボタンクリックで日付を表示する -->
<div class="gutter"/>
<div aura:id="msg">
You entered: <ui:outputDate aura:id="oDate" value="" />
</div>
</div>
</aura:component>
// controller.js
({
handleClick: function(cmp, event, helper) {
// 説明簡略化のため、max の値をここでも定義
const maxDateObj = moment("2018-07-20");
// 入力された日付を moment にセット
const inputObj = moment(cmp.find("datepicker1").get("v.value"));
// max を超えていないか判定
if (maxDateObj.diff(inputObj) < 0) {
// max 以降の日付が入力された場合、何もしない
return;
}
// max 以内の日付であれば、反映する
cmp.find("oDate").set("v.value", inputObj.format("YYYY-MM-DD"));
}
})
2018-07-25 を入力した場合は、SUBMIT ボタン下の You entered:
に反映されないことが確認できました。
まとめ
max 以降の日付が入力された場合の挙動を制御することができました。min についても同様です。
将来的に今回のような部分までケアされると良いですね
蛇足
本投稿を書きながら思ったのですが業務では
「範囲外が入力された時点で SUBMIT
ボタンを非活性にする」
などという要件も考えられますね。。。
Datepicker からフォーカスが外れた (onblur) 場合と、値が更新された場合 (onchange) を活用すれば実現できるのですが・・・長くなってしまったので、余力があればまたいつか