我有以下结构
<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回发中使用&amp;从内部选项卡和内部选项卡中重新渲染来自整个层级的外部:
<f:ajax event="click" render="@form" execute="@form" />
或
<p:ajax process="@form" partialSubmit="false" update="@form" />
问题在于活动索引仅针对外部手风琴持续存在,而不是儿童手风琴(虽然查看POST数据,也会发送儿童手风琴活动索引)。我做错了什么,或者我不应该期望这个开箱即用?
什么可行?
另一方面,我知道我可以通过提供模型和每个节点上的字段来手动管理活动索引,这将保留此数据。 (没有测试,但经过大量的pf帖子/所以页面,这是我所期待的)
<p:accordionPanel activeIndex="#{model.activeIndex}"...
<p:accordionPanel activeIndex="#{node.activeIndex}"...
任何人都可以确认第二种方法是唯一的方法吗?或者我在第一种情况下做错了什么?
Primefaces 3.4.2
Glassfish堆栈 3.1.2.2
更新05.04.2013
后一种方法也不起作用。因为在ajax POST node.activeIndex接收值""
(并且只正确设置了根活动索引)
数据方案(POST数据详情)
javax.faces.partial.ajax=true javax.faces.source=j_idt106:j_idt271:1:j_idt121:j_idt110:0:j_idt113:featureRepeater:11:featureCheckboxP javax.faces.partial.execute=gridDetailPage javax.faces.partial.render=gridDetailPage javax.faces.behavior.event=valueChange javax.faces.partial.event=change gridDetailPage=gridDetailPage j_idt106:j_idt271:1:j_idt121:j_idt110_active=0,1 // INNER OPEN TABS j_idt106:j_idt271_active=0,1 // OUTER OPEN TABS javax.faces.ViewState=4232962649695633063:-8633977119414123467
javax.faces.partial.ajax=true javax.faces.source=j_idt106:j_idt271:1:j_idt121:j_idt110:0:j_idt113:featureRepeater:0:featureCheckboxP javax.faces.partial.execute=gridDetailPage javax.faces.partial.render=gridDetailPage javax.faces.behavior.event=valueChange javax.faces.partial.event=change gridDetailPage=gridDetailPage j_idt106:j_idt271:1:j_idt121:j_idt110_active=0 // INNER OPEN TABS j_idt106:j_idt271_active=0,1 // OUTER OPEN TABS javax.faces.ViewState=4232962649695633063:-8633977119414123467
答案 0 :(得分:2)
andyba :
提出的解决方案 “为了确保传播activeIndex值,您需要勾选accordionPanel,只需在顶部添加一个空的p:ajax标记(<p:ajax/>
)即可。等级accordionPanel 和这项工作。“
不幸的是,这不起作用(尝试每个组合外部,内部,两个+与&amp;没有activeIndex)。
但这确实
无需设置activeIndex,这没关系,因为在服务器端我对索引不感兴趣):
在外面:
<p:ajax event="tabChange"/>
(基本上是您的解决方案的限制形式
在内部手风琴中我添加了:
<p:ajax event="tabChange" process="@this" update="@form"/>
这意味着在我的情况下,只有整个表单重新呈现才能更改内部选项卡状态
不幸的是,由于页面结构复杂,这会增加难看的闪烁。我希望我可以在tabchange上没有ajax的情况下解决它。
找到最后,我结束了自己的解决方案。那就是:
如果约束我们以相同的顺序显示相同数量的手风琴,我们可以将它们的状态保存在一个字符串中,每个打开一个包含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>