【问题标题】:p:calendar trigger javascript method after first view is renderedp:calendar 在呈现第一个视图后触发 javascript 方法
【发布时间】:2023-03-09 07:35:02
【问题描述】:

我想创建一个组合来增强<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);
}

所有这些都可以正常工作:当我更改月份时,新月份会使用来自dateInfoMap 的正确信息显示在alterCalendar() 中所做的所有更改。

但是,这仅在我第一次更改月份后完成。 &lt;p:calendar&gt; 在第一次渲染后似乎没有触发事件。我现在如何申请alterCalendar()

两种可能的解决方案似乎都不适合像这样的组件:

  1. 如果存在触发要呈现日历的 ajax,我可以告诉组件的用户调用 javascript 函数作为 oncomplete-callback。这 a) 对用户不好,b) 并不总是适用,c) 很难动态获取日历实例,而无需手动输入组件 ID。

  2. 我可以使用$(document).ready()之类的表达式,但是如果日历的渲染确实是由另一个ajax触发的,这可能不起作用,并且1c)也适用于此。

是否有另一种更优雅的方式可以动态获取日历的实例或 ID?

编辑:我尝试使用&lt;p:calendar&gt;beforeShow 属性,但它没有做任何事情。我正在使用 Primefaces 6.2

【问题讨论】:

  • 你知道你可以把javascript直接放在xhtml里吗?不需要 inputHidden,您还可以通过在 javascript 中的 p:calendar 之后调用它来调用初始 alterCalendar?
  • inputHidden 用于使 bean 变量 dateInfoMap 在 Javascript 中可用。有什么替代方案?
  • 如果我将javascript直接放在xhtml中,如何动态获取日历ID或实例? [...]&lt;/p:calendar&gt;&lt;script&gt;console.log(this);&lt;/script&gt;[...] 只是给了我window 对象
  • inputhidden,见:stackoverflow.com/questions/2547814/… 你可以有任何动态变量是唯一的
  • 关于日历,您可以动态分配一个widgetvar并使用它来访问它

标签: javascript primefaces calendar


【解决方案1】:

kukeltje的帮助下,我可以解决问题并消除其他问题。

1) 密钥是#{cc.clientId}。这在复合命名空间中可用,并根据 Javascript 的需要为我提供组件的 ID。

2) 表单不应该是组合的一部分。 See here for more info.

3) 我可以在 xhmtl 页面的 Javascript 中的任何位置使用#{...}

4) 我不需要隐藏输入字段,我可以使用RequestContext 将值传递给 Javascript 函数。如果我使用#{cc.attrs.bean.dateInfoMap},则该值不会始终是最新的,因为它是使用&lt;p:ajax&gt; 呈现的。 See here for more info.

这让我想到了这个解决方案:

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>

在 bean 中:

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
  });
  });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-16
    • 1970-01-01
    • 2023-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多