如何知道 JSF 组件的 id 以便我可以在 Javascript 中使用

IT技术 javascript jsf
2021-02-02 19:50:39

问题:有时您希望使用 javascript 访问组件 getElementById,但 id 是在 JSF 中动态生成的,因此您需要一种获取对象 id 的方法。我在下面回答你如何做到这一点。


原始问题: 我想使用如下代码。如何在我的 Javascript 中引用 inputText JSF 组件?

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <head>
       <title>Input Name Page</title>
        <script type="javascript" >
          function myFunc() {
            // how can I get the contents of the inputText component below          
            alert("Your email address is: " + document.getElementById("emailAddress").value);
          }
       </script>
    </head>
    <h:body>
        <f:view>
            <h:form>
                Please enter your email address:<br/>
                <h:inputText id="emailAddresses" value="#{emailAddresses.emailAddressesStr}"/>
                <h:commandButton onclick="myFunc()" action="results" value="Next"/>
            </h:form>
        </f:view>
    </h:body>
</html>

更新:这篇文章JSF2.0 中客户端标识符讨论了使用如下技术:

<script type="javascript" >
  function myFunc() {
    alert("Your email address is: " + document.getElementById("#{myInptTxtId.clientId}").value);
  }
</script>

<h:inputText id="myInptTxtId" value="backingBean.emailAddress"/>
<h:commandButton onclick="myFunc()" action="results" value="Next"/>

在上面的示例中,建议组件id的属性inputText创建一个可以使用 EL 访问的对象#{myInptTxtId}文章继续指出 JSF 2.0getClientId()UIComponent添加了零参数方法从而允许#{myInptTxtId.clientId}上面建议构造获取组件的实际生成的 id。

虽然在我的测试中这不起作用。其他任何人都可以确认/否认。下面建议的答案存在上述技术没有的缺点。所以最好知道上述技术是否真的有效。

6个回答

您需要完全使用 JSF 在生成的 HTML 输出中分配的 ID。右键单击 Web 浏览器中的页面,然后选择View Source这正是 JS 看到的 HTML 代码(你知道,JS 在 webbrowser 中运行并拦截 HTML DOM 树)。

给定一个

<h:form>
    <h:inputText id="emailAddresses" ... />

它看起来像这样:

<form id="j_id0">
    <input type="text" id="j_id0:emailAddress" ... />

j_id0生成的 HTML<form>元素的生成 ID在哪里

您宁愿给所有 JSFNamingContainer组件一个固定值,id这样 JSF 就不会自动生成它们。<h:form>是其中之一。

<h:form id="formId">
    <h:inputText id="emailAddresses" value="#{emailAddresses.emailAddressesStr}"/>

这样,表单就不会像这样获得自动生成的 ID j_id0,而输入字段将获得一个固定的 ID formId:emailAddress然后,您可以在 JS 中直接引用它。

var input = document.getElementById('formId:emailAddress');

从那时起,您可以像往常一样继续使用 JS 代码。例如通过input.value.

也可以看看:


更新根据您的更新:你误解了这个博客的文章。特殊#{component}引用是指计算 EL 表达式当前组件,这仅在组件本身的任何属性内起作用。任何你想要的也可以实现如下:

var input = document.getElementById('#{emailAddress.clientId}');

with(注意binding视图,你绝对不应该将它绑定到 bean)

<h:inputText binding="#{emailAddress}" />

但这很丑陋。最好使用以下方法,将生成的 HTML DOM 元素作为 JavaScriptthis引用传递给函数

<h:inputText onclick="show(this)" />

function show(input) {
    alert(input.value);
}

如果您使用的是 jQuery,您甚至可以通过使用样式类作为标记接口将它们抽象化来更进一步

<h:inputText styleClass="someMarkerClass" />

$(document).on("click", ".someMarkerClass", function() {
    var $input = $(this);
    alert($input.val());
});
或者,您可以设置 <h:form prependId="false"> 并且表单 ID 不会将其自身添加到您的 DOM 元素中。
2021-03-10 19:50:39
可以这么说,我的主要目标是组件通信。您的解决方案不允许单击按钮并触发访问页面中任何其他组件的 javascript。请参阅下面我的答案以获得更好的解决方案。
2021-03-12 19:50:39
@maple:您只需要注意重复的 ID。对于像这样的简单形式,您确实可以这样做。但是对于视图中具有重复组件的复杂页面,您希望将其保留为默认值。
2021-03-29 19:50:39
为什么要将它绑定到支持 bean?那只是杂乱。就像在我的答案更新的第一部分一样,立即绑定到视图。
2021-04-01 19:50:39
@BalusC 虽然我给我的 p:commandButton 提供了一个固定的 id 调用,但它仍然自动生成一个名为 id="j_idt39:speakout" 的 id
2021-04-06 19:50:39

回答:所以这是我最满意的技术。不需要做太多奇怪的事情来找出组件的 id。请记住,这样做的全部意义在于,您可以id从页面上的任何位置了解组件的名称,而不仅仅是从实际组件本身。这是关键。我按下一个按钮,启动 javascript 功能,它应该能够访问任何其他组件,而不仅仅是启动它的组件。

此解决方案不需要任何“右键单击”并查看 id 是什么。这种类型的解决方案很脆弱,因为 id 是动态生成的,如果我更改页面,我每次都必须经历这些废话。

  1. 将组件绑定到支持 bean。

  2. 在任何地方引用绑定组件。

所以这里是如何做到这一点的示例。

假设:我有一个 *.xhtml 页面(可能是 *.jsp)并且我已经定义了一个支持 bean。我也在使用 JSF 2.0。

*.xhtml 页面

<script>
  function myFunc() {
    var inputText = document.getElementById("#{backBean.emailAddyInputText.clientId}")                 
    alert("The email address is: " + inputText.value );
  }
</script>

<h:inputText binding="#{backBean.emailAddyInputText}"/>
<h:commandButton onclick="myFunc()" action="results" value="Next"/>

BackBean.java

UIInput emailAddyInputText;

确保也为这个属性创建你的 getter/setter。

将组件绑定到 bean 是完全没有必要的,只会给 bean 增加混乱。就像在我的答案更新的第一部分一样直接绑定到视图。
2021-03-25 19:50:39

Id 是动态生成的,因此您应该为所有父元素定义名称以避免类似 j_id123 的 id。

请注意,如果您使用 jQuery 来选择元素 - 则应该在冒号前使用双斜线:

    jQuery("my-form-id\\:my-text-input-block\\:my-input-id")

代替:

    jQuery("my-form-id:my-text-input-block:my-input-id")

对于 Richfaces,您可以在 jsf 页面上使用 el 表达式:

    #{rich:element('native-jsf-input-id')} 

选择javascript元素,例如:

    #{rich:element('native-jsf-input-id')}.value = "Enter something here";

您可以在生成时查看 HTML 源代码并查看 id 设置为什么,以便您可以在 JavaScript 中使用它。因为它是一个表单,所以它可能会在它前面加上表单 id。

id 是自动生成的。
2021-04-06 19:50:39

我知道这不是 JSF 的方式,但是如果您想避免 ID 痛苦,您可以为选择器设置一个特殊的 CSS 类。只要确保使用一个好名字,这样当有人阅读类名时就可以清楚地知道它是用于这个目的的。

<h:inputText id="emailAddresses" class="emailAddressesForSelector"...

在你的 JavaScript 中:

jQuery('.emailAddressesForSelector');

当然,您仍然需要手动管理类名的唯一性。我确实认为这是可维护的,只要您不在可重用组件中使用它。在这种情况下,您可以使用约定生成类名。

使用 jQuery 选择器应该很容易找到元素。但对我来说,它看起来像 ID 中的冒号(我认为这是不允许的)把它弄乱导致选择器不起作用:stackoverflow.com/questions/609382/jquery-selector-id-ends-with
2021-03-17 19:50:39
@PanuHaaramo 你可以转义特殊字符
2021-03-19 19:50:39