2

我有这个表单,其中包含约 170 个单独的文本框,其中包含会话范围 bean 中的值。要求仅在组件具有特定 CSS 类时才提交值。

我最初的方法是在 UPDATE_MODEL_VALUES 创建一个 PhaseListener 并在那里测试 CSS 类。如果该类是受影响的类,我将组件的值设置为 null。然后在前端,我使用通用 JavaScript 方法将类切换为焦点。这意味着我只需要添加对每个组件的更改:

... styleClass="examfieldgrey" onfocus="whiteField(this);"

考虑到我需要更改多少组件,这很好。

在我重构我的 e 表单以使用多个 h 表单标签之前,这一切正常。现在 CSSclass 正在前端切换,但没有保存此更改。相位侦听器正在获取旧类。

我认为这显然与我在 jQuery/javascript 中切换类有关。我想知道的是:

  1. 有没有更好的方法来做到这一点?一个最好意味着我不必修改 170 多个组件?
  2. 如果我必须继续使用 Javascript 来切换课程,有没有办法可以将更改从 javascript 发布回来?

抱歉,如果这是一个明显的问题,我对 JSF 生命周期还是有点陌生​​。

我正在使用 JSF 2.0 MyFaces

作为参考,这里是我的表单上需要过滤的组件的示例:

<h:inputTextarea 
  id="inputVal" 
  styleClass="midTextArea examfieldgrey"
  onfocus="whiteField(this);"
  value="#{bean.form.val}"/>

其中“examfieldgrey”是我在确定是否要阻止组件时测试的类。

和 whiteField 方法:

function whiteField(field){
    if(! jQuery(field).hasClass("examfieldgrey")){
        return;
    }
    jQuery(field).removeClass("examfieldgrey");
    jQuery(field).addClass("examfieldwhite");
}

以及我过滤的阶段方法之前的阶段侦听器:

// TODO: make whatever mode allows ghosting to be configurable outside of
// the system (perhaps in the config file)
/**
 * Before the model is updated, test each component's CSS on the form.  If the 
 * CSS style is 'examfieldgrey' set the value to null so it doesn't get submitted
 */
@Override
public void beforePhase(PhaseEvent arg0) {

    //We need the session to get the backing bean
    if (arg0.getFacesContext().getExternalContext().getSessionMap() == null) {
        return;
    }

    //get the measurements bean so we can determine the form mode 
    if (arg0.getFacesContext().getExternalContext().getSessionMap()
            .get("measurements") == null) {
        return;
    }

    //ensure the bean is the expected data type, it should always be this type.  I'm just paranoid ;)
    if (!(arg0.getFacesContext().getExternalContext().getSessionMap()
            .get("measurements") instanceof MeasurementsController)) {

        return;
    }

    //get, convert and check the backing bean's mode.  We only filter if the mode is COPY
    if (((MeasurementsController) arg0.getFacesContext()
            .getExternalContext().getSessionMap().get("measurements"))
            .getMode() != FormMode.COPY) {

        return;
    }

    //recursivly traverse the componenets and filter the ones who have the CSS class
    traverseChildren(arg0.getFacesContext().getViewRoot().getChildren());
}

/**
 * Traverse a List of UIComponenets and check the CSS.  If it's the 'examfieldgrey' class
 * and the component is a UIInput component, set the value to null. 
 * @param children  a List of the componenets to filter on the form.
 */
private void traverseChildren(List<UIComponent> children) {
    debugLevelCount++;
    if (children == null || children.size() == 0) {
        debugLevelCount--;
        return;
    }

    for (UIComponent component : children) {
        if (component instanceof UIInput) {
            if (component.getAttributes() != null
                    && component.getAttributes().get("styleClass") != null
                    && component.getAttributes().get("styleClass")
                            .toString().contains("examfieldgrey")) {
                ((UIInput) component).setValue(null);
            } else {
                debugPrintAllow(component);
            }
            continue;
        }
        traverseChildren(component.getChildren());
    }
    debugLevelCount--;
}

忽略打印​​功能,它们什么都不做;)

多谢你们!

编辑

这是一个复制操作,因此支持 bean 在构建 bean 之后在其中具有值。如果我点击提交并且支持 bean 尚未填充,则使用 primefaces 选择器的选项非常好。但我不确定它是否能够真正清除这些值。

需要注意的另一件事是,我在表单对象的实例中引用了值。我不知道这是否有帮助,但它没有出现在我的原始帖子中。

4

2 回答 2

5

要求仅在组件具有特定 CSS 类时才提交值。

如果您碰巧已经使用PrimeFaces或愿意使用它,从最新的 3.3 版本开始,您可以使用新的@()选择器语法,该语法接受基于 jQuery 的 CSS 选择器processupdatePrimeFaces ajax 组件的属性(相当于JSF 标准组件的execute和属性) )。render<f:ajax>

例如

<p:commandButton ... process="@(.foo)" />

或者

<p:ajax ... process="@(.foo)" />

将指示 JSF处理类名为foo.


现在 CSSclass 正在前端切换,但没有保存此更改。相位侦听器正在获取旧类。

那是因为您没有使服务器端的 JSF 组件树与客户端的 HTML DOM 树保持同步。您只是在客户端进行更改,而不通知 JSF。CSS 类不会作为请求参数发送到服务器端,只有 HTML 表单输入值。您基本上需要通过 JSF 而不是 JS/jQuery 更改 CSS 类,以便更改也反映在 JSF 组件树中。

然而,实现这一点并不完全是微不足道的,而且可能是浪费的。因此,最简单的方法是使用带有@()选择器支持的 PrimeFaces。此选择器在客户端进行评估并转换为与选择器匹配的 JSF 可理解的组件客户端 ID 字符串。因此,这充分考虑了客户端的变化。

于 2012-06-03T18:14:18.917 回答
0

我能够通过为表单上的每个字段创建一个布尔值映射来解决这个问题,其中字符串键是字段的 ID。每个值代表天气或不复制字段。我在模糊上使用 ajax 更新这个值。我将 CSS 类设置为基于地图中该字段的布尔值。

渲染效果不太好。最初我是在焦点上做这一切,但很快就很明显,试图渲染一个焦点上的文本框实际上会失去对文本框的焦点。所以,在焦点上,我只是调用了一个快速的 js 函数来切换类,就像我最初所做的那样。

由于 css 类是根据前端的映射选择的,因此在调用阶段侦听器之前会更新它并正确过滤组件。

感谢BalusC的帮助!

于 2012-06-06T14:57:49.220 回答