Advanced customization with slots and render callbacks for dynamic day cell content
declarative — pass <div slot="day-YYYY-MM-DD"> children into the component
Use named slots like slot="day-2025-01-15" to customize specific dates with HTML. This is the simplest approach for marking special dates.
<web-daterangepicker>
<div slot="day-2025-01-15" class="custom-day-content">
<strong>15</strong>
<span class="event-dot"></span>
</div>
<div slot="day-2025-01-20" class="custom-day-content">
<span class="emoji-day">🎉</span>
<small>Holiday</small>
</div>
</web-daterangepicker>
JS callback: el.renderDayCallback = (data) => HTMLElement
Use picker.renderDayCallback to completely replace day cell content with custom logic. Perfect for dynamic data like prices, availability, or complex styling.
const picker = document.getElementById('callback-full');
// Simulated price data
const prices = {
'2025-02-14': 299, // Valentine's Day premium
'2025-02-15': 199,
'2025-02-21': 149,
'2025-02-22': 149
};
picker.renderDayCallback = (data) => {
const price = prices[data.dateString];
const container = document.createElement('div');
container.className = 'custom-day-content';
const dayNum = document.createElement('strong');
dayNum.textContent = data.dayNumber;
container.appendChild(dayNum);
if (price) {
const priceTag = document.createElement('span');
priceTag.className = 'price-tag';
priceTag.textContent = `$${price}`;
container.appendChild(priceTag);
}
return container;
};
JS callback: el.renderDayContentCallback — adds to the default cell
Use picker.renderDayContentCallback to ADD content to the default day cell rendering. The day number is rendered by the component, your callback adds extra elements.
const picker = document.getElementById('callback-augment');
// Inject CSS for event-dot into Shadow DOM
picker.customStylesCallback = () => `
.event-dot {
position: absolute;
bottom: 2px;
right: 2px;
width: 6px;
height: 6px;
background: #3b82f6;
border-radius: 50%;
}
`;
// Simulated events
const events = {
'2025-03-05': true,
'2025-03-12': true,
'2025-03-19': true,
'2025-03-26': true
};
picker.renderDayContentCallback = (data) => {
if (events[data.dateString]) {
const dot = document.createElement('span');
dot.className = 'event-dot';
return dot;
}
return null; // No extra content
};
getDateMetadataCallback returns dayClass + customStylesCallback ships the CSS
Rainbow weekday visualization showing traffic intensity: Monday (light blue, lowest) → Friday (red, highest), weekends in pink/purple. Uses customStylesCallback to inject CSS into Shadow DOM, then getDateMetadataCallback returns dayClass to style the entire day cell wrapper.
const picker = document.getElementById('callback-weekends');
picker.customStylesCallback = () => `
.weekday-sun { background: linear-gradient(135deg, #e9d5ff 0%, #d8b4fe 100%); }
.weekday-mon { background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%); }
.weekday-tue { background: linear-gradient(135deg, #bfdbfe 0%, #93c5fd 100%); }
.weekday-wed { background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); }
.weekday-thu { background: linear-gradient(135deg, #fed7aa 0%, #fdba74 100%); }
.weekday-fri { background: linear-gradient(135deg, #fca5a5 0%, #f87171 100%); }
.weekday-sat { background: linear-gradient(135deg, #fbcfe8 0%, #f9a8d4 100%); }
`;
picker.getDateMetadataCallback = ({ date }) => {
const dayOfWeek = date.getDay();
const weekdayClasses = ['weekday-sun', 'weekday-mon', 'weekday-tue',
'weekday-wed', 'weekday-thu', 'weekday-fri', 'weekday-sat'];
return { dayClass: weekdayClasses[dayOfWeek] };
};
Per-day slots take priority over callbacks. Use slots for specific dates, callbacks for patterns.
const picker = document.getElementById('callback-mixed');
const cloudyDates = ['2025-05-03', '2025-05-04', '2025-05-10', '2025-05-17', '2025-05-18'];
// Callback applies to all weekends
picker.renderDayContentCallback = (data) => {
// This won't apply to May 25 (has slot)
if (data.isWeekend) {
if (cloudyDates.includes(data.dateString)) {
return '☁️';
}
return '☀️';
}
return null;
};
Complete example showing availability, pricing, and booking state.
const picker = document.getElementById('booking-system');
const bookingData = {
'2025-06-07': { available: true, price: 180, booked: false },
'2025-06-14': { available: true, price: 220, booked: false },
'2025-06-21': { available: false, price: 0, booked: true }
};
const toLocalISO = (d) =>
`${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
// Disable booked dates
picker.getDateMetadataCallback = ({ date }) => {
const info = bookingData[toLocalISO(date)];
if (info && info.booked) return { isDisabled: true };
return null;
};
picker.renderDayCallback = (data) => {
const info = bookingData[data.dateString];
const container = document.createElement('div');
// ... build day number + price/booked label ...
return container;
};
// Calculate price on selection
picker.addEventListener('date-select', (event) => {
if (event.detail.dateRange) {
// sum bookingData[...].price across the range
}
});
(pick a date anywhere on this page)