为什么嵌套的动态手风琴面板会在@form renderer上丢失activeIndex信息?



我有以下结构

<h:form>
<!-- some elements -->
<p:accordionPanel id="outer" multiple="true" var="node" dynamic="false" value="#{model.nodes}">
    <p:tab id="outerId">
        <p:accordionPanel id="inner" multiple="true" dynamic="false" var="child" value="#{node.children}">
            <p:tab id="innerId">
              <!-- iterated components -->
            </p:tab>
        </p:accordionPanel>
    </p:tab>
</p:accordionPanel>
</h:form>

然后我尝试在ajax回发&从内部选项卡中进行渲染&从整个层次结构的外部:

<f:ajax event="click" render="@form" execute="@form" />

<p:ajax process="@form" partialSubmit="false" update="@form" />

问题是活动索引只被持久化到外部手风琴,而不是子手风琴(尽管查看POST数据,子手风琴活动索引也被发送)。是我做错了什么,还是我不应该期望它开箱即用?

怎么做

另一方面,我知道我可以通过在模型和每个节点上提供一个字段来手动管理活动索引,这将持久化该数据。(没有测试,但在挖掘了大量的帖子/页面后,这是我所期望的)

<p:accordionPanel activeIndex="#{model.activeIndex}"...
       <p:accordionPanel activeIndex="#{node.activeIndex}"...

有人能确认第二种方法是唯一的方法吗?还是我在第一种情况下做错了什么?

Primefaces 3.4.2

Glassfish stack 3.1.2.2

更新05.04.2013

后一种方法也不起作用。因为在ajax POST节点上。activeIndex接收值""(只有根活动索引设置正确)

数据场景(POST数据详情)

  1. 加载页面。
  2. 打开前两个外部选项卡。
  3. 从第二个外部标签打开前两个内部标签。
  4. 点击页面内的元素
  5. POST数据
<>之前javax.faces.partial.ajax = truejavax.faces.source = j_idt106: j_idt271:1: j_idt121: j_idt110:0: j_idt113: featureRepeater: 11: featureCheckboxPjavax.faces.partial.execute = gridDetailPagejavax.faces.partial.render = gridDetailPagejavax.faces.behavior.event = valueChangejavax.faces.partial.event =改变gridDetailPage = gridDetailPagej_idt106:j_idt271: j_idt121:j_idt110_active=0,1//INNER OPEN TABS . j_idt106:j_idt271: j_idt121:j_idt110_active=0,1j_idt106:j_idt271_active=0,1//OUTER OPEN TABSjavax.faces.ViewState = 4232962649695633063: -8633977119414123467之前
  1. 呈现的页面有前两个外部选项卡,并且只有从第二个外部选项卡打开的第一个内部选项卡(错误)
  2. 下面的POST只发布当前(错误)配置
<>之前javax.faces.partial.ajax = truejavax.faces.source = j_idt106: j_idt271:1: j_idt121: j_idt110:0: j_idt113: featureRepeater: 0: featureCheckboxPjavax.faces.partial.execute = gridDetailPagejavax.faces.partial.render = gridDetailPagejavax.faces.behavior.event = valueChangejavax.faces.partial.event =改变gridDetailPage = gridDetailPagej_idt106:j_idt271: j_idt121:j_idt110_active=0//INNER OPEN TABSj_idt106:j_idt271_active=0,1//OUTER OPEN TABSjavax.faces.ViewState = 4232962649695633063: -8633977119414123467

方案由andyba提出:

"为了确保activeIndex值被传播,你需要tickle的accordionPanel,你通过简单地添加一个空的p:ajax标签(<p:ajax/>)在顶层accordionPanel和这个工作。"

不幸的是,没有工作(尝试了每一个组合外,内,两个+与&没有activeIndex)。

但是这个

  • 不需要设置activeIndex,这是OK的,因为在服务器端我对索引不感兴趣):

  • 在外层:

    <p:ajax event="tabChange"/>
    

    (这基本上是你的解决方案的限制形式

  • )
  • 在内部手风琴中我添加了:

    <p:ajax event="tabChange" process="@this" update="@form"/>
    

    这意味着在我的情况下,只有一个完整的表单渲染是必要的改变内部标签状态

不幸的是,由于复杂的页面结构,这会增加难看的闪烁。我希望我能解决它没有ajax的tabchange。

也可在primefaces论坛找到

<标题> 20130510 更新

最后,我终于酿造出了自己的解决方案。即:

约束我们以相同的顺序显示相同数量的手风琴,我们可以将它们的状态保存在一个字符串中,其中每个打开手风琴为1,每个关闭手风琴为0。因此,解决方案如下:

var CONTAINER_SELECTOR = 'selector of container containing all accordions';
// called whenever we click on an accordion (see assignment in init)
var saveAccordionsState = function () {
  var state = '';
  $(CONTAINER_SELECTOR + ' .ui-accordion-header').each(function (i, el) {
      // for every accordion put a 0 or 1 in the state string
      state += ($(el).hasClass('ui-state-active') ? '1' : '0');
  });
  // put the state string in an input that will be submitted to the server
  $('#accordionState').val(state); 
};
// this method is called right after accordions are rendered
var init = function () {
    // retrieve the saved state
    var state = $('#accordionState').val();
    // get reference to all accordions
    var $accordions = $('.ui-accordion-header');
    // turn jquery effects off for quick restoration (otherwise we'll have glitches
    $.fx.off = true;
    if (state === '' || $accordions.length !== state.length) { // if no state defined 
        // open all accordions by simulating a click on them
        $('.ui-accordion-header').not('.ui-state-active').trigger('click');
    } else { // otherwise
        for (var i = state.length - 1; i >= 0; --i) {
            var $accordion = $($accordions[i]);
            var c = state[i];
            // for every accordion that is in the opposite state
            if ((c === '1' && !$accordion.hasClass('ui-state-active')) ||
                (c === '0' && $accordion.hasClass('ui-state-active'))) {
                $accordion.trigger('click'); // simulate a click on its header to toggle it
            }
        }
    }
    // turn effects back on
    $.fx.off = false;
    // save the state
    saveAccordionsState();
    // assign the save state method to every accordion header click
    $('.ui-accordion-header', $featureTable).click(saveAccordionsState);
};

xhtml看起来像这样:

<h:form>
    <p:accordionPanel ... >
        <p:tab ... >
            <h:panelGroup ... >
                <p:accordionPanel ... >
                    <p:tab ... >
                        <h:panelGroup ... />
                    </p:tab>
                </p:accordionPanel>
            </h:panelGroup>
        </p:tab>
    </p:accordionPanel>
    <h:inputHidden id="accordionState" value="#{bean.accordionState}"/>
    <script type="text/javascript">
        init();
    </script>
</h:form>

相关内容

  • 没有找到相关文章

最新更新