如何在 h:datatable jsf2.0 中对单选按钮进行分组

发布于 2024-11-30 12:57:32 字数 178 浏览 4 评论 0原文

我在 JSF2 的 h:datatable 中有一列单选按钮,但我找不到对它们进行分组的方法。这意味着所有这些都可以同时选择,而单选按钮的全部意义在于,在任何给定时间只能选择一个。我确信会有标准的方法来做到这一点。

我正在用我的脸。如果确实需要的话可以使用richfaces。

任何人都可以帮忙解决这个问题吗?

I have a column of radio buttons in h:datatable in JSF2 but I can not find a way to group them. Meaning all of them can be selected at the same time where as whole point of radio button is so that only one can be selected at any given time. I am sure there will be standard way of doing it.

I am using myfaces. Can use richfaces if really needed to.

Can any one help with this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

野味少女 2024-12-07 12:57:32

中使用标准 JSF 组件时,您需要将一段 JavaScript 引入游戏,以取消选中所有其他组件当选中一个单选按钮时,同一列中的单选按钮。

<h:column>
    <h:selectOneRadio onclick="uncheckOthers(this);">
</h:column>

function uncheckOthers(radio) {
    var name = radio.name.substring(radio.name.lastIndexOf(':'));
    var elements = radio.form.elements;
    for (var i = 0; i < elements.length; i++) {
        if (elements[i].name.substring(elements[i].name.lastIndexOf(':')) == name) {
            elements[i].checked = false;
        }
    }
    radio.checked = true;
}

When using standard JSF <h:selectOneRadio> component inside a <h:dataTable> you'll need to bring a shot of JavaScript into the game which unchecks all other radio buttons in the same column when one is checked.

<h:column>
    <h:selectOneRadio onclick="uncheckOthers(this);">
</h:column>

with

function uncheckOthers(radio) {
    var name = radio.name.substring(radio.name.lastIndexOf(':'));
    var elements = radio.form.elements;
    for (var i = 0; i < elements.length; i++) {
        if (elements[i].name.substring(elements[i].name.lastIndexOf(':')) == name) {
            elements[i].checked = false;
        }
    }
    radio.checked = true;
}
黄昏下泛黄的笔记 2024-12-07 12:57:32

首先,在 HTML 或 JSP 中如此简单的事情在 JSF 中却很难做到,这是可笑的。这些增加的层次应该让生活变得更轻松,而不是更困难。但在我看来,它们只是让生活变得更加困难。我以前很喜欢他们。现在,我是一名 Java 勒德分子,现在提倡采用更简单的方法,其中包括更少的“听起来很酷的‘技术’”,以及更多的“简单有效的东西,而不需要整周努力去做”。以前只需要 5 分钟的事情”。无论如何,我在过去 3 个工作日内尝试让 JSF 中的简单功能正常工作,从而导致其他单选按钮取消选择并使用户选择的单选按钮保持不变。我尝试了几种方法,包括自定义标签库(“overkill”,已定义)以及一些仅产生大量堆栈跟踪的内容的混合和匹配。我最终求助于 Javascript,并承认创建一个可靠的通用解决方案是不可能的。我在其他地方读过类似的投诉。好吧,我的抱怨结束了。以下是我为杀死我的特定 JSF 单选按钮龙所做的事情:

在 .xhtml 页面上:

<ui:composition template="../template.xhtml"
   ...
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:f="http://java.sun.com/jsf/core"
   xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
   ...
>

<a4j:loadScript src="/resources/scripts/custom.js" />
...
<ui:param name="pageBean" value="#{recordsBean}" />
...

<h:dataTable id="tblMine" 
   value="#{pageBean.records}" 
   var="item" 
   border="1" celpadding="0" cellspacing="0" 
   style="font-size=10px;text-align: center;"
>

<h:column> 
<f:facet name="header">
<h:panelGroup><h:panelGrid cellspacing="0" cellpadding="0" border="0" 
     id="rowSelect" columns="1" width="100%"><h:outputText 
        value="Select" /></h:panelGrid></h:panelGroup>
</f:facet>

<h:selectOneRadio id="userselectedrecord"
       onclick="javascript:clearOtherRadioButtons(event);" >
  <f:selectItem itemValue="#{item.recordid}" 
      itemLabel="" /> <!-- I set itemLabel to "" because in my case,
                           I don't want any text next to the radio btns -->
</h:selectOneRadio>
</h:column>
...
... and the rest of the page ...

在 custom.js 文件中,我有:

function clearOtherRadioButtons(evnt)
{
 // Have to try 'currentTarget', then 'srcElement'.  Issue is Firefox
 // supports 'currentTarget' but IE does not.  IE supports 'srcElement'.
 var btn = (evnt.currentTarget) ? evnt.currentTarget : evnt.srcElement;
 var matchindexlocn = btn.id.indexOf('userselectedrecord');
 var btnidstarttxt = btn.id.substring(0, 
            matchindexlocn + 18 ); // 'userselectedrecord' length = 18
 var elementid = '';
 var i = 0;
 var ele = null;
 var allElements = document.getElementsByTagName('*');

 for(i = 0; i < allElements.length; i++)
 {
     elementid = allElements[i].id;
     if ( (elementid.indexOf(btnidstarttxt) == -1) && 
          (elementid.indexOf('_') > -1) )
     {
       try
       {
        ele = document.getElementById(elementid);
        ele.checked = false;
        } catch (e) {}
     }
  }
} // function clearOtherRadioButtons(evnt)

就是这样。通过一些解释来说明 Javascript 中的 if():

elementid.indexOf(btnidstarttxt) == -1

-->这会将元素范围缩小到那些以 JSF 添加的对象 ID 文本开头的元素,该文本与与传入事件关联的按钮组相关联。我们不想想要取消选择事件被传递到函数的按钮组中的按钮。

elementid.indexOf('_') > -1

-->这进一步将元素范围缩小到只有实际按钮,因为 JSF 向按钮元素 ID 添加了下划线。

设置 check = false 的代码位于 try..catch 块中的原因是为了防止逻辑周围的任何假设出现问题并且情况未得到处理。如果您了解环境并且可以控制元素 ID,那么应该没问题。然而,万一发生某些变化,例如,应用程序的主机服务器安装了一些新版本的 JSF 库,该库覆盖了应用程序的类加载策略(在工作环境中,据我们所知,这些事情可能会超出我们的控制范围)现在以不同的方式分配这些元素 id,应用程序不会因突然的令人讨厌的 Javascript 错误而中断,或更糟糕的是,单选按钮选择会停止工作。我猜想可能发生的最糟糕的情况是可以同时选择多个无线电 btns 并且用户可以提交它们。我认为一个好的预防措施是添加更多 Javascript 代码来验证用户只提交一个选项,或者在服务器端验证用户的提交。

看,仅仅管理单选按钮状态就需要做太多工作。

First, it's ludicrous that something this simple in HTML or JSP is so hard to do in JSF. These added layers should be making life easier, not harder. But it seems to me they just make life harder. I used to like them. Now I am a Java Luddite, advocating now in favor of simpler approaches that include less in the way of "new cool-sounding 'technologies'" and more in the way of "stuff that just plain works without having to struggle all week to do something that used to take just 5 minutes". Anyway, I have tried the past 3 working days to get the simple functionality in JSF to work that causes other radio buttons to deselect and leave the user-selected one unchanged. I tried several approaches including a custom tag library ("overkill", defined) and a number of mixing and matching of stuff that only produced a lot of stacktraces. I finally fell back on Javascript and accepted that creating a reliably generalized solution was not likely. I have read similar complaints elsewhere. OK, my gripe session is over. Here's what I did to slay my particular JSF-radio-button dragon:

On the .xhtml page:

<ui:composition template="../template.xhtml"
   ...
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:f="http://java.sun.com/jsf/core"
   xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
   ...
>

<a4j:loadScript src="/resources/scripts/custom.js" />
...
<ui:param name="pageBean" value="#{recordsBean}" />
...

<h:dataTable id="tblMine" 
   value="#{pageBean.records}" 
   var="item" 
   border="1" celpadding="0" cellspacing="0" 
   style="font-size=10px;text-align: center;"
>

<h:column> 
<f:facet name="header">
<h:panelGroup><h:panelGrid cellspacing="0" cellpadding="0" border="0" 
     id="rowSelect" columns="1" width="100%"><h:outputText 
        value="Select" /></h:panelGrid></h:panelGroup>
</f:facet>

<h:selectOneRadio id="userselectedrecord"
       onclick="javascript:clearOtherRadioButtons(event);" >
  <f:selectItem itemValue="#{item.recordid}" 
      itemLabel="" /> <!-- I set itemLabel to "" because in my case,
                           I don't want any text next to the radio btns -->
</h:selectOneRadio>
</h:column>
...
... and the rest of the page ...

In the custom.js file, I have:

function clearOtherRadioButtons(evnt)
{
 // Have to try 'currentTarget', then 'srcElement'.  Issue is Firefox
 // supports 'currentTarget' but IE does not.  IE supports 'srcElement'.
 var btn = (evnt.currentTarget) ? evnt.currentTarget : evnt.srcElement;
 var matchindexlocn = btn.id.indexOf('userselectedrecord');
 var btnidstarttxt = btn.id.substring(0, 
            matchindexlocn + 18 ); // 'userselectedrecord' length = 18
 var elementid = '';
 var i = 0;
 var ele = null;
 var allElements = document.getElementsByTagName('*');

 for(i = 0; i < allElements.length; i++)
 {
     elementid = allElements[i].id;
     if ( (elementid.indexOf(btnidstarttxt) == -1) && 
          (elementid.indexOf('_') > -1) )
     {
       try
       {
        ele = document.getElementById(elementid);
        ele.checked = false;
        } catch (e) {}
     }
  }
} // function clearOtherRadioButtons(evnt)

That's it. By way of some explanation re that if() in the Javascript:

elementid.indexOf(btnidstarttxt) == -1

--> This narrows the elements down to those that do not start with the JSF-added object ID text that is associated with the button group associated with the passed-in event. We do not want to unselect the button in the button group whose event was passed into the function.

elementid.indexOf('_') > -1

--> This narrows the elements down further to only actual buttons since JSF adds underscores to the button element IDs.

The reason the code that sets checked = false is in a try..catch block is just in case something goes wrong with any presumptions around the logic and the circumstance is not handled. If you know the environment and can control the element ids, you should be fine. However on the off chance that something changes due to, let's say for example, the app's host server getting some new version JSF library installed that overrides your app's classloading policy (in a work environment, these things as we know can happen beyond our control) that now assigns these element ids differently, the app won't break with a sudden nasty Javascript error or worse yet, the radio button selection just stops working. Worst I guess that can happen is that multiple radio btns can be selected at the same time and the user can submit them. I suppose a good precaution to take is to add yet more Javascript code to validate that only one option is being submitted by the user, or validate the user's submission server-side.

See, way too much work just to manage radio button state.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文