2

我浏览了 SO,并找到了一些答案,这些答案引导我更接近于获得工作单选按钮,但我现在被困住了。

我有按钮,但无法获得所选按钮的值。

我正在使用 JSF,因此#{searchFlightsBean.setDir()}

这是我目前拥有的:

<h:panelGrid>
    <div class="btn-group" data-toggle-name="is_private" data-toggle="buttons-radio" >
        <button type="button" value="0" class="btn" data-toggle="button">Public</button>
        <button type="button" value="1" class="btn" data-toggle="button">Private</button>
    </div>
    <h:inputHidden id="hiddenDir" value="0" valueChangeListener="#{searchFlightsBean.setDir()}"  onchange="submit()"/>
</h:panelGrid>

<script>
$(function() {
    $('div.btn-group[data-toggle-name]').each(function() {
        var group = $(this);
        var form = group.parents('form').eq(0);
        var name = group.attr('data-toggle-name');
        var hidden = $('input[name="' + name + '"]', form);
        $('button', group).each(function() {
            var button = $(this);
            button.on('click', function() {
                hidden.val($(this).val());
            });
            if (button.val() == hidden.val()) {
                button.addClass('active');
                #{searchFlightsBean.setDir(button.value)}
            }
        });
    });
});
</script>

在我的 bean 中,当setDir()被调用时,我正在记录它接收到的值,如下所示:

public void setDir(ValueChangeEvent e) {
    this.dir = e.getNewValue().toString();
    log.info("NEW DIRECTION: " + this.getDir());
}

它不记录 -setDir()永远不会被调用。由于某种原因,标签valueChangeListener上的属性h:inputHidden不起作用。我错过了什么吗?

4

2 回答 2

1

您的具体问题是因为您使用valueChangeListener了错误的方式造成的。

<h:inputHidden ... valueChangeListener="#{searchFlightsBean.setDir()}">

这与方法签名不匹配。您应该省略括号()

<h:inputHidden ... valueChangeListener="#{searchFlightsBean.setDir}">

否则 JSF 需要一个无参数的setDir()方法。然后,您将无法在 JavaScript 中触发change输入元素上的事件。因此onchange="submit()"从不调用。你应该hidden.trigger("change")在 JS 中实现这一点。

但是,这毕竟有些笨拙。您正在发送一个完整的同步请求,并且您的 JS 代码相当复杂(一旦您对表单进行 ajax 更新就会停止工作)。如果您确实使用 JSF 2.x,我建议您引入<f:ajax>— 不幸的是,它在 中不起作用<h:inputHidden>,因此<h:inputText style="display:none">— 并$.on()在 jQuery 中使用以保持功能正常工作,即使您对 DOM 进行 ajax 更新。

<h:form>
    <div class="btn-group" data-toggle-name="is_private" data-toggle="buttons-radio" >
        <button type="button" value="0" class="btn" data-toggle="button">Public</button>
        <button type="button" value="1" class="btn" data-toggle="button">Private</button>
    </div>
    <h:inputText id="is_private" value="#{bean.dir}" style="display: none;">
        <f:ajax listener="#{bean.changeDir}" />
    </h:inputText>
    <!-- Note: <h:inputText id> must be exactly the same as <div data-toggle-name> -->
</h:form>

<h:outputScript>
    $(document).on("click", "[data-toggle=buttons-radio] button", function() {
        var $button = $(this);
        var id = $button.closest(".btn-group").attr("data-toggle-name");
        var $input = $button.closest("form").find("input[id$=':" + id + "']");

        if ($input.val() != $button.val()) {
            $input.val($button.val()).trigger("change");
        }
    });
</h:outputScript>

(注意应该是整个脚本真的应该放在.js你自己包含的文件中<h:outputScript name="some.js" target="body">;注意你不需要也不需要$(document).ready()混乱$(function() {});还请注意,非常 JS 函数可以在所有其他<div data-toggle="buttons-radio">组上重复使用而无需更改)

使用这个 bean:

private Integer dir;

public void changeDir() {
    System.out.println("New direction: " + dir);
}

// ...

(应该注意的是,当您在方法中没有做任何相关的事情时changeDir(),您可以完全省略整个方法,<f:ajax>然后恢复<h:inputText style="display:none"><h:inputHidden>删除.trigger("change")并依赖常规表单提交。它会工作得很好)

于 2013-08-22T14:20:06.007 回答
1

您不能只通过 JavaScript 中的表达式语言调用 (#{...}) 调用任何支持 bean 函数。

您可以做的是使用 a4j:jsFunction 将您的 bean 方法提供给 java 脚本代码。这可能看起来像这样:

<a4j:jsFunction name="setDir" action="#{searchFlightsBean.setDir()}" ajaxSingle="true">
    <a4j:param name="dir" assignTo="#{searchFlightsBean.dir}" />
</a4j:jsFunction>

请参阅http://docs.jboss.org/richfaces/latest_3_3_X/en/devguide/html/a4j_jsFunction.htmlhttp://showcase.richfaces.org/richfaces/component-sample.jsf?demo=jsFunction&skin=blueSky

于 2013-08-22T09:06:59.903 回答