I want to create a composite that serves as an enhancement of <p:calendar>
. This is what I have:
calendar.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="bean" />
</composite:interface>
<composite:implementation>
<h:form id="calendarForm" class="calendarForm" >
<h:outputScript library="js" name="calendar.js" />
<p:inputText type="hidden" id="dateInfoMap" class="dateInfoMap" value="#{cc.attrs.bean.dateInfoMap}"/>
<p:calendar
id="calendar"
value="#{cc.attrs.bean.selectedDate}"
mode="inline" >
<p:ajax event="viewChange" listener="#{cc.attrs.bean.makeDateInfoMapForMonth}" update="dateInfoMap" oncomplete="alterCalendar(this)" />
</p:calendar>
</h:form>
</composite:implementation>
</html>
The function cc.attrs.bean.makeDateInfoMapForMonth
creates an object that contains information about each day of the current month (as obtainable from the viewChange event) and stores it in cc.attrs.bean.dateInfoMap
.
calendar.js
function alterCalendar(ajaxRequest) {
let calendar = document.getElementById(ajaxRequest.source);
let dateInfoMap = getDateInfoMap(calendar);
// do stuff with this calendar and dateInfoMap
}
function getDateInfoMap(calendar) {
return JSON.parse($(calendar).closest(".calendarForm").find(".dateInfoMap")[0].value);
}
All of this works as it should: When I change the month, the new month gets displayed with all the changes made in alterCalendar()
using the correct information from dateInfoMap
.
However, this is only done after I changed the month for the first time.
<p:calendar>
does not seem to fire an event after it has been rendered the first time. How can I have alterCalendar()
be applied at this moment?
Two possible solutions both seem inappropriate for a component like this:
I could tell the user of the component to call a javascript function as an oncomplete-callback if there is an ajax that triggers the calendar to be rendered. This is a) not nice for the user, b) not always applicable, and c) it would be hard to obtain the calendar instance dynamically, without having to manually type the components id.
I could use an expression like
$(document).ready()
, but if the calendar's rendering is indeed triggered by another ajax, this will probably not work, and 1 c) also applies here.
Is there another, more elegant way where the calendar's instance or ID can be obtained dynamically?
Edit: I tried using the beforeShow
attribute of <p:calendar>
, but it does not do anything. I am using Primefaces 6.2