Les calendriers et les sélecteurs de date sont toujours difficiles à mettre en place dans un formulaire. Heureusement, il existe souvent des packages JS qui nous permettre de mettre ça en place facilement.
Pour afficher un calendrier sélecteur de dates, nous allons utiliser le package Flatpickr.
Tout d’abord il faut ajouter le package flatpickr dans votre application.
$ yarn add flatpickr
Nous allons maintenant créer notre formulaire dans la page show
des Flat
.
<!-- app/views/flats/show.html.erb -->
<!-- [...] -->
<div class="container">
<div class="form-wrapper">
<h2>Book a flat</h2>
<%= simple_form_for [@flat, @booking] do |f| %>
<%= f.input :start_date, as: :string,
required: false,
input_html: { id: "range_start" } %>
<%= f.input :end_date, as: :string,
required: false,
input_html: { id: "range_end" } %>
<%= f.button :submit, "Book", class: "btn btn-primary" %>
<% end %>
</div>
</div>
Maintenant que le formulaire est créé, nous allons créer un tableau de hash avec les locations déjà existantes. On récupère d’abord l’id de l’appartement. Enfin, avec une méthode .map
on transforme les réservations en hash avec la date de début et de fin.
# app/controllers/flats_controller.rb
class FlatsController < ApplicationController
# [...]
def show
@flat = Flat.find(params[:id])
@bookings = @flat.bookings
@bookings_dates = @bookings.map do |booking|
{
from: booking.start_date,
to: booking.end_date
}
end
end
# [...]
end
Une fois créé, on place le tableau de hash dans la vue sous forme de data-set à la fin de la page.
<!-- app/views/flats/show.html.erb -->
<!-- [...] -->
<div id="booking-form-div"
data-bookings="<%= @bookings_dates.to_json %>">
</div>
S’il n’est pas déjà existant vous devez créer un dossier plugins
dans app/javascript
puis créer un fichier flatpickr.js
.
$ mkdir -p app/javascript/plugins
$ touch app/javascript/plugins/flatpickr.js
// app/assets/stylesheets/application.scss
// [...]
@import "flatpickr/dist/flatpickr";
Dans le fichier app/javascript/plugins/flatpickr.js
on récupère les données dans la div avec getElementbyID
. Puis on les parse en JSON et on grise les réservations avec le disable
.
// app/javascript/plugins/flatpickr.js
import flatpickr from "flatpickr"
import rangePlugin from "flatpickr/dist/plugins/rangePlugin"
const initFlatpickr = () => {
const bookingForm = document.getElementById('booking-form-div');
if (bookingForm) {
const bookings = JSON.parse(bookingForm.dataset.bookings);
flatpickr("#range_start", {
plugins: [new rangePlugin({ input: "#range_end"})],
minDate: "today",
inline: true,
dateFormat: "Y-m-d",
"disable": bookings,
})
}
};
export { initFlatpickr };
Ensuite dans le fichier application.js
il faut importer la fonction initFlatpickr
, puis l’appeler quand Turbolinks est chargé.
// app/javascript/packs/application.js
import { initFlatpickr } from '../plugins/flatpickr';
document.addEventListener('turbolinks:load', () => {
initFlatpickr();
})
Maintenant on va cacher les champs du dates pour ne laisser apparaître que le calendrier.
Tout d’abord, il faut ajouter un label au calendrier. Ensuite on va cacher les deux champs avec la classe Bootstrap d-none
.
<!-- app/views/flats/show.html.erb -->
<div class="container">
<div class="form-wrapper">
<h2>Book a flat</h2>
<%= simple_form_for [@flat, @booking] do |f| %>
<%= f.input :start_date, label: "Sélectionnez vos dates:",
as: :string,
required: false,
input_html: { id: "range_start", class: "d-none"} %>
<%= f.input :end_date, label: false,
as: :string,
required: false,
input_html: { id: "range_end", class: "d-none" } %>
<%= f.button :submit, "Book", class: "btn btn-primary" %>
<% end %>
</div>
</div>
Si vous souhaitez effectuer une vérification sur les dates avant d’enregistrer la réservation, vous pouvez utiliser la méthode overlaps?
Souvent sur ce type d’application, le prix total s’affiche et se modifie en fonction des dates sélectionnées. Le tuto pour l’affichage dynamique, c’est ici
Publié le 24/07/2019