p:calendar 在呈现第一个视图后触发 javascript 方法
p:calendar trigger javascript method after first view is rendered
我想创建一个组合作为 <p:calendar>
的增强。这是我的:
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>
函数 cc.attrs.bean.makeDateInfoMapForMonth
创建一个对象,其中包含有关当月每一天的信息(可从 viewChange 事件中获取)并将其存储在 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);
}
所有这些都按预期工作:当我更改月份时,新月份会显示 alterCalendar()
中使用 dateInfoMap
中的正确信息所做的所有更改。
但是,这是我第一次更改月份后才完成的。
<p:calendar>
似乎在第一次呈现后不会触发事件。 alterCalendar()
如何在此时应用?
两种可能的解决方案似乎都不适合这样的组件:
我可以告诉组件的用户调用一个 javascript 函数作为 oncomplete-callback 如果有一个 ajax 触发日历被呈现。这是 a) 对用户不好,b) 并不总是适用,c) 很难动态获取日历实例,而不必手动键入组件 ID。
我可以使用像 $(document).ready()
这样的表达式,但是如果日历的呈现确实是由另一个 ajax 触发的,这可能不起作用,并且 1 c) 也适用这里。
是否有另一种更优雅的方式可以动态获取日历的实例或 ID?
编辑:我尝试使用 <p:calendar>
的 beforeShow
属性,但它没有任何作用。我正在使用 Primefaces 6.2
在kukeltje的帮助下,我解决了问题,也排除了其他问题。
1) 密钥是 #{cc.clientId}
。这在复合命名空间中可用,并根据需要为我提供组件的 ID Javascript.
2) 表单不应该是组合的一部分。 See here for more info.
3) 我可以在 xhmtl 页面 Javascript 中的任何地方使用 #{...}
。
4) 我不需要隐藏输入字段,我可以使用 RequestContext
将值传递给 Javascript 函数。如果我使用 #{cc.attrs.bean.dateInfoMap}
,该值不会总是最新的,因为它是使用 <p:ajax>
呈现的。
这让我想到了这个解决方案:
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:outputScript library="js" name="calendar.js" />
<p:calendar
id="calendar"
value="#{cc.attrs.bean.selectedDate}"
mode="inline" >
<p:ajax
event="viewChange"
listener="#{cc.attrs.bean.makeDateInfoMapForMonth}"
oncomplete="alterCalendar('#{cc.clientId}', args.dateInfoMap)" />
</p:calendar>
<script>
alterCalendar('#{cc.clientId}', '#{cc.attrs.bean.dateInfoMap}');
</script>
</composite:implementation>
</html>
豆中:
public void makeDateInfoMapForMonth(DateViewChangeEvent event) {
dateInfoMap = //...
RequestContext.getCurrentInstance().addCallbackParam("dateInfoMap", dateInfoMap);
}
calendar.js
function alterCalendar(componentClientId, dateInfoMap) {
let calendar = document.getElementById(componentClientId + ":calendar");
dateInfoMap = JSON.parse(dateInfoMap);
$(calendar).ready(function () {
// do stuff
});
});
}
我想创建一个组合作为 <p:calendar>
的增强。这是我的:
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>
函数 cc.attrs.bean.makeDateInfoMapForMonth
创建一个对象,其中包含有关当月每一天的信息(可从 viewChange 事件中获取)并将其存储在 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);
}
所有这些都按预期工作:当我更改月份时,新月份会显示 alterCalendar()
中使用 dateInfoMap
中的正确信息所做的所有更改。
但是,这是我第一次更改月份后才完成的。
<p:calendar>
似乎在第一次呈现后不会触发事件。 alterCalendar()
如何在此时应用?
两种可能的解决方案似乎都不适合这样的组件:
我可以告诉组件的用户调用一个 javascript 函数作为 oncomplete-callback 如果有一个 ajax 触发日历被呈现。这是 a) 对用户不好,b) 并不总是适用,c) 很难动态获取日历实例,而不必手动键入组件 ID。
我可以使用像
$(document).ready()
这样的表达式,但是如果日历的呈现确实是由另一个 ajax 触发的,这可能不起作用,并且 1 c) 也适用这里。
是否有另一种更优雅的方式可以动态获取日历的实例或 ID?
编辑:我尝试使用 <p:calendar>
的 beforeShow
属性,但它没有任何作用。我正在使用 Primefaces 6.2
在kukeltje的帮助下,我解决了问题,也排除了其他问题。
1) 密钥是 #{cc.clientId}
。这在复合命名空间中可用,并根据需要为我提供组件的 ID Javascript.
2) 表单不应该是组合的一部分。 See here for more info.
3) 我可以在 xhmtl 页面 Javascript 中的任何地方使用 #{...}
。
4) 我不需要隐藏输入字段,我可以使用 RequestContext
将值传递给 Javascript 函数。如果我使用 #{cc.attrs.bean.dateInfoMap}
,该值不会总是最新的,因为它是使用 <p:ajax>
呈现的。
这让我想到了这个解决方案:
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:outputScript library="js" name="calendar.js" />
<p:calendar
id="calendar"
value="#{cc.attrs.bean.selectedDate}"
mode="inline" >
<p:ajax
event="viewChange"
listener="#{cc.attrs.bean.makeDateInfoMapForMonth}"
oncomplete="alterCalendar('#{cc.clientId}', args.dateInfoMap)" />
</p:calendar>
<script>
alterCalendar('#{cc.clientId}', '#{cc.attrs.bean.dateInfoMap}');
</script>
</composite:implementation>
</html>
豆中:
public void makeDateInfoMapForMonth(DateViewChangeEvent event) {
dateInfoMap = //...
RequestContext.getCurrentInstance().addCallbackParam("dateInfoMap", dateInfoMap);
}
calendar.js
function alterCalendar(componentClientId, dateInfoMap) {
let calendar = document.getElementById(componentClientId + ":calendar");
dateInfoMap = JSON.parse(dateInfoMap);
$(calendar).ready(function () {
// do stuff
});
});
}