更新於 2024/02/17閱讀時間約 9 分鐘

【套件筆記 - JS】時間選擇器 flatpickr.js

不喜歡 HTML 原生的時間選擇器外型嗎?試試看 flatpickr 吧!

以下是使用 flatpickr 做簡單的示例,以及 flatpickr 使用注意事項。

Demo

一、官網資源

flatpickr 官網:https://flatpickr.js.org/


二、CDN 安裝

flatpickr

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>

Bootstrap CSS(建立表單用,非必要)

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">


三、使用範例

https://codepen.io/annchou_illu/pen/oNmZbBX

3-1. 目標功能

  1. 時間輸入格須具備點選 年/月/日/時/分
  2. 時間輸入格採 24 時制
  3. 開始時間不能早於當前本地時間
  4. 結束時間只能選擇當前一個月內的本地時間
  5. 時間輸入格的開始時間不能晚於結束時間

3-2. 示範步驟

  1. 規劃版位
  2. DOM 元素綁定
  3. flatpickr 初始化
  4. 判斷時間先後順序,提示錯誤警告

3-3. 實作

  1. 規劃版位 HTML
    寫入開始與結束日期輸入格,以及錯誤訊息提示,並將錯誤訊息先使用 d-none (Bootstrap 樣式)隱藏。
    input 時間 type 的寫法請參考 MDN,我們在這裡新增一個 dateSelector 的 class 在兩個時間輸入格上,這待會可以用來做 flatpicr 初始化綁定。其實 flatpicr 綁 id 也可以,但因為 id 必須是唯一值,class 可以重複,所以綁 class 比較單純。
    目前已經可以使用 HTML 原生的選擇器了。
<ul class="d-flex flex-column gap-3 p-5 border border-2 w-50 list-unstyled">
<li>
<label for="startDate" class="mb-16 mb-md-12">開始日期</label>
<input type="datetime-local" id="startDate" name="startDate" placeholder="請點選日期" class="dateSelector">
</li>
<li>
<label for="endDate" class="mb-16 mb-md-12">結束日期</label>
<input type="datetime-local" id="endDate" name="endDate" placeholder="請點選日期" class="dateSelector">
<p class="mt-3 text-danger d-none dateAlert">※ 結束日期須晚於開始日期</p>
</li>
</ul>

原生 HTML 選擇器

  1. DOM 元素綁定
    綁定錯誤訊息提示。
const dateAlert = document.querySelector(".dateAlert");

3. 設定 flatpicr 初始化
注意 MDN 說明提到 type="datetime-local" 在部分瀏覽器會自動轉成 type="text",所以建議綁 id 或是 class 比較安全。
更多說明:初始化方式初始化屬性設定

因為這個範例是未使用 moment 的範例,所以我們需要藉由 Date 處理。

const currentTime = new Date()

config = {
enableTime: true, //可選時與分
dateFormat: "Y/m/d H:i", //時間格式
time_24hr: true, //24 時制
minuteIncrement: 15, //分鐘每次選擇間隔單位
allowInput: true, //可輸入控制
minDate: "today", //可選最小時間,可直接接受 'today' 字串
maxDate: currentTime.setMonth(currentTime.getMonth() + 1), //可選最大時間,從今天起一個月
}

flatpickr(".dateSelector", config);
  1. 測試是否能取值
    我們也能利用 flatpickr 做 onChange 監聽,做些執行動作。在 config 中加入以下程式碼,傳入的三個值依序代表
    selectedDate:相當 Date.prototype.toString(),返回的字串 "Sun Dec 24 2023 03:00:00 GMT+0800 (台北標準時間)"
    dateStr:返回字串 "2023/12/24 03:00",格式是剛才我們在 config 中設定的 dateFormat
    instance:flatpickr 實例,如果用 console.dir 展開可以在其中找到 inputinput.id 可用來判斷目前正被點選的 DOM
onChange: function (selectedDates, dateStr, instance) {
console.log(`你現在點選的是 ${instance.input.id},時間為 ${selectedDates} / ${dateStr}`);
}

Demo

  1. 上面步驟有提到 instance.input.id 可以用作判斷正被點選的 DOM,所以我們改寫 onChange,讓它能將參數傳輸,引發能辨別時間先後的函式執行
onChange: function (selectedDates, dateStr, instance) {
checkDateTime(dateStr, instance.input.id);
}
  1. 辨別兩時間先後
    因為每次 onChange 觸發,checkDateTime 都會跑一次,所以要先把開始日期和結束日期宣告在外面當全域變數。我們即可以使用比較運算子來判斷開始日期是否晚於結束日期。如果開始日期較晚,則移除錯誤訊息的 d-none,讓錯誤訊息顯示。
let startDateValue = null
let endDateValue = null

function checkDateTime(dateStr, id) {
if (id === "startDate"){
startDateValue = dateStr
}

if (id === "endDate"){
endDateValue = dateStr
}

if (startDateValue>endDateValue){
dateAlert.classList.remove("d-none");
}else{
dateAlert.classList.add("d-none");
}

}
  1. 以上即完成所有項目


四、flatpickr 注意事項

  1. 可使用 flatpickr("input[type=datetime-local]", config); 綁定,但 MDN 表示 type="datetime-local" 在少數瀏覽器中會降階為 type="text",所以還是建議使用 class 或 id 綁定會比較好。
  2. 部分設置如限制可選時間、每次可選時間間隔的設定,因為手機會變成使用每個系統原生的選擇器,所以將造成可用手機原生選擇器選擇被限制的時間,但在手機畫面顯示時會產生錯誤。
  3. 如果要將 A input 的時間傳遞至 B input 顯示,需於使用 flatpickr 綁定的 B input 使用 setDate(時間, true),否則在手機版無法顯示。
分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.