Kalendář se vám na webu určitě hodí, potřebuje ho každá druhá stránka. Musíme ale vždy kvůli jednoduchému kalendáři stahovat plugin třetí strany? V tomto článku se spolu podíváme na to, jak si vyrobit vlastní kalendář založený na JavaScriptu a Vue3 (composition API). Na konci článku zjistíte, že vyrobit si vlastní kalendář není až taková věda, jak by se na první pohled mohlo zdát.
Výsledek naší práce bude vypadat takhle:
Na čem náš kalendář bude fungovat:
- Vue3 (composition API)
- SASS
- VueUse (využití onClickOutside)
- V době výroby byl kalendář vyráběn s LTS NodeJS verzí 18.15.0
Kdo nechce ztrácet čas vysvětlením, tak si může rovnou naklonovat náš GitHub repozitář. Než si podrobně vysvětlme repozitář, tak si jej naklonujeme. Doporučuji mít otevřený repozitář alespoň na druhém monitoru/ záložce, abyste si z výkladu vzali co nejvíce. Teď už ale pojďme na to.
Naklonování repozitáře a spuštění projektu
Repozitář si naklonujete do vašeho pc následujícím příkazem git clone
https://github.com /fordevsczsk/vue3-calendar.git
.
Po naklonování je třeba nainstalovat balíčky příkazem npm install
a projekt spustíme přes npm run dev
. Nezapomeňte tyto 2 příkazy spouštět ve složce repozitáře - cd vue3-calendar
. Pokud vše úspěšně proběhlo, tak nám konzole vypíše adresu, na kterém projekt běží.
Příprava
Projekt začal jednoduchým nainstalováním Vue3 přes příkaz npm init vue@latest
. Vue3 nám nainstalovalo pár základních komponent a CSSek, ty jsme všechny odstranili, protože je nebudeme v našem projektu potřebovat. Zůstal nám tedy čistý App.vue.
Když jsme měli vyčištěný repozitář, tak jsme nainstalovali SCSS příkazem npm install -D sass-loader sass
a přidali naše vlastní CSSka pomocí Sass 7-1 architektury, kterou jsme již popisovali zde.
Komponenta InputCalendar.vue
Kalendářem simulujeme situaci klasického formuláře, ve kterém si uživatel může vybrat datum a ten se přidá do formuláře. Z toho důvodu název komponenty tedy dáme InputCalendar.vue.
HTML (<template>)
Šablona je jednoduchá, máme zde label a následně button, který nám otevírá kalendář. Do buttonu posíláme jako text naformátované datum, které jsme vybrali. V mnoha případech je žádoucí, aby se prvek formuláře vyvolal na klik labelu. V našem případě to neřešíme, ale pokud to chcete, stačí doplnit do labelu for a párovat na button s ID. Do naší šablony jsme dále vložili komponentu CalendarDropdown
, která je zodpovědná za samostný dropdown kalendáře. CalendarDropdown
nám vrací v emitu hodnotu vybraného data.
Co by vás mohlo překvapit, tak je použití ref="calendarWrapper"
na obalovací div. Je to z toho důvodu, abychom si uměli odchytit element, na který jsme klikli, v případě, že klikneme mimo tento element, tak se kalendář zavře.
Script
Ve scriptu využíváme onClickOutside z VueUse. Což je kolekce utilities pro Vue. onClickOutside se postará o to, že když klikneme mimo náš vybraný element, tak dokážeme spustit funkci (v našem případě zavřeme kalendář).
Otevírání a zavírání kalendáře je řešení přes proměnnou isDropdownActive
, kterou handlujeme metodou toggleDropdown
.
Vybraný den ukládáme do selectedDay
, což je hodnota, kterou získáváme z komponenty CalendarDropdown.vue
.
Pro formátování data, které vypisujeme nepoužíváme žádnou speciální knihovnu, ale formátování probíhá v computed formattedSelectedDay
. Kde si vezmeme přes vanilla javascript selectedDay.getDate()
/ .getMonth()
/ .getFullYear()
požadovaná data.
Styly
Ke stylům se dostaneme níže, kde popíšeme styly jako celek. V této komponentě pouze naimportujeme (přes modernější @use
) náš .scss soubor.
Komponenta CalendarDropdown.vue
Tato komponenta nám zobrazuje samotný kalendář v dropdownu, pojďme se podívat na její kód.
HTML (<template>)
Kalendář obsahuje hlavičku a poté samotný kalendář. V hlavičce najdeme tlačítka pro zobrazení předchozího a následujícího měsíce, dále aktuálně vybraný měsíc a rok. Samotný kalendář obsahuje také hlavičku (PO - NE) a tělo kalendáře, které vypisuje dny v měsíci, ty získáváme pomocí metody v JS, kterou si popíšeme níže.
Script
Ve scriptu, abychom znali české dny a měsíce, tak jsme si je uložili do proměnných WEEKDAYS
a MONTHS
. Tady už je script zajímavější než v předchozí komponentě.
Proměnné, které jsou pro nás důležité, tak jsou selectedMonth
, kde jako výchozí hodnotu ukládáme aktuální měsíc, dále selectedYear
, kde znovu ukládáme aktuální rok a selectedDay
, kde necháváme prázdné. Do rodičovské komponenty (InputCalendar.vue
), posíláme dateSelect
, který si vypočítáme níže.
Abychom uměli zobrazit dny v kalendáři, tak je potřebujeme získat. K tomu nám slouží getDaysInMonth
, kde pošleme jako argument měsíc a rok, pro který chceme dny získat. Tato metoda nám vrátí všechny dny v daném měsíci.
getCalendarPlaceholder
slouží k tomu, abychom uměli odsadit první den z levé strany. Přece jen každý měsíc nezačíná pondělím. Funkce nám vrátí první den v měsíci.
daysInselectedMonth
computed nám již vrátí v přehledném objektu výsledky funkcí getCalendarPlaceholders
a getDaysInMonth
. Tuto computed používáme v HTML v loopě k zobrazení počtu dní a odsazení z levé strany.
Metoda toggleRange
nám pouze mění hodnoty, které máme uloženy v selectedMonth
a selectedYear
, takže díky tomu se dokážeme posouvat v kalendáři na předchozí/následující měsíce.
V momentě, kdy v kalendáři klikneme na nějaký den, tak posíláme hodnotu do naší komponty InputCalendar.vue
, kde ji naformátujeme a zobrazujeme uživateli.
Styly
Do komponenty includujeme soubor s SCSS pro dropdown.
Styly
Styly máme rozděleny do již zmiňované SASS 7-1 architektury. Využíváme CSS reset, který v nějaké formě najdeme asi v každém webu – složka base/_reset.scss
. Zajímavostí stylů je možná funkce rem()
, která nám konvertuje px na rem jednotky, s tím, že do volání funkce posíláme px. Její definici naleznete v abstracts/_functions.scss
. Mně osobně se použití této funkce velmi osvědčilo i ve větších projektech.
Styly pro komponenty jsou uloženy ve složce components/calendar
, kde najdeme stejné názvy souborů jako mají .vue komponenty, do kterých jsou includovány. Tady nic moc extra zajímavého nenajdeme, layout je řešen pomocí CSS flexbox modelu a v souborech najdete použití BEMu.
Závěr
Jedná se o demonstraci jednoduché komponenty s kalendářem a toho, že není vždy nutné kvůli jednoduchému kalendáři vkládat ihned novou knihovnu. Náš kalendář můžete volně použít ve vašem projektu, ohnout ho nebo upravit na jinou technologii, například React, což by nemělo být složité, protože velká část je napsána ve vanilla javascriptu.
Samozřejmě kalendář má své mouchy, například chybí v něm označení svátků, to by šlo zase udělat podobně jako s definováním dní a měsíců. Tedy další proměnnou, které řeknete kdy jsou české svátky a následně v šabloně budete kontrolovat zda daný den se rovná tomu, který máte definován ve vašem poli. Případně někomu může chybět funkce, že se dá pohybovat v kalendáři pouze po měsících, někdo by možná chtěl i po letech.
V případě, že máte nějaké dotazy nebo chcete pomoci s rozšířením kalendáře, tak se zastavte na našem Discorde.