如何以相同的顺序维护手风琴面板?
How to maintain accordionPanels in the same order?
我在 Primefaces 中使用 accordionPanel。当我刷新页面时,顺序改变了!例如:我有 1,2,3 然后它们变成 2,3,1 或 3,2,1!每次刷新页面时面板的顺序都会改变!
<p:panel toggleable="true" header="Mesure" rendered="#{not empty mesureController.varValues['structure']}">
<p:accordionPanel value="#{mesureController.structureComposants.toArray()}" var="sc">
<p:tab title="#{sc.nomComposant}" closable="false">
<p:dataTable value="#{sc.plans.toArray()}" var="plan" id="plansTable" emptyMessage="">
<p:column headerText="Plan">
<p:outputLabel value="#{plan.nomPlan}"/>
</p:column>
<p:column headerText="Image">
<p:lightBox styleClass="imagebox" id="lighbox1"
rendered="#{not empty plan.image}">
<h:outputLink
value="data:image/png;base64,#{ligneBean.getImageContentsAsBase64(plan)}"
title="#{plan.commentaire}">
<img src="data:image/png;base64,#{ligneBean.getImageContentsAsBase64(plan)}"
style="height: 120px; width: auto; margin-right: 10px;"/>
</h:outputLink>
</p:lightBox>
</p:column>
<p:column headerText="#{mesureController.varValues['typeMesure']}">
<ui:repeat value="#{plan.reperes.toArray()}" var="repere">
<p:panelGrid columns="5" layout="grid">
<p:outputLabel id="nom_repere" value="#{repere.nomRepere}"/>
<p:tooltip id="toolTipGrow" for="nom_repere" value="#{repere.commentaire}"
position="left"/>
<p:outputLabel value="#{repere.repereConfig.temperature.minTemperature}"
title="min temperature"
rendered="#{mesureController.selectedTypeMesure.name().equals('TEMPERATURE')}"/>
<p:outputLabel value="#{repere.repereConfig.epaisseur.minEpaisseur}"
title="min epaisseur"
rendered="#{mesureController.selectedTypeMesure.name().equals('EPAISSEUR')}"/>
<p:inputText value="#{mesureController.currentMesure.structureDetails[repere]}"
disabled="#{not mesureController.firstTask}"
converter="javax.faces.Double" converterMessage="valeur numerique"
style="width: 50px">
<p:ajax event="change" listener="#{mesureController.validateMesureValue}"
update=":iwFormsForm">
</p:ajax>
</p:inputText>
<p:outputLabel value="#{repere.repereConfig.temperature.maxTemperature}"
title="max temperature"
rendered="#{mesureController.selectedTypeMesure.name().equals('TEMPERATURE')}"/>
<p:outputLabel value="#{repere.repereConfig.epaisseur.maxEpaisseur}"
title="max epaisseur"
rendered="#{mesureController.selectedTypeMesure.name().equals('EPAISSEUR')}"/>
</p:panelGrid>
</ui:repeat>
</p:column>
</p:dataTable>
</p:tab>
</p:accordionPanel>
<ui:fragment rendered="#{mesureController.typeStructure.equals('FOUR')}">
<ui:include src="graph.xhtml"/>
</ui:fragment>
<p:accordionPanel value="#{mesureController.fourZones.toArray()}" var="fz" activeIndex="0,1,2,3,4,5">
<p:tab title="#{fz.description}">
<p:dataTable value="#{fz.points.toArray()}" var="fpoint" id="fpointsTable" emptyMessage="" >
<p:column headerText="point">
<p:outputLabel value="#{fpoint.description} #{fpoint.position}(m)"/>
</p:column>
<p:column headerText="#{mesureController.varValues['typeMesure']}">
<p:panelGrid columns="3" layout="grid">
<p:outputLabel value="#{fpoint.temperature.minTemperature}" title="min temperature"
rendered="#{mesureController.selectedTypeMesure.name().equals('TEMPERATURE')}"/>
<p:outputLabel value="#{fpoint.epaisseur.minEpaisseur}" title="min epaisseur"
rendered="#{mesureController.selectedTypeMesure.name().equals('EPAISSEUR')}"/>
<p:inputText value="#{mesureController.currentMesure.fourDetails[fpoint]}"
converter="javax.faces.Double" converterMessage="valeur numerique"
style="width: 50px">
<p:ajax event="change" update=":iwFormsForm"
listener="#{mesureController.validateMesureFourValue}"/>
</p:inputText>
<p:outputLabel value="#{fpoint.temperature.maxTemperature}" title="max temperature"
rendered="#{mesureController.selectedTypeMesure.name().equals('TEMPERATURE')}"/>
<p:outputLabel value="#{fpoint.epaisseur.maxEpaisseur}" title="max epaisseur"
rendered="#{mesureController.selectedTypeMesure.name().equals('EPAISSEUR')}"/>
</p:panelGrid>
</p:column>
</p:dataTable>
</p:tab>
</p:accordionPanel>
<p:accordionPanel value="#{mesureController.tadZones.toArray()}" var="tz">
<p:tab title="#{tz.description}">
<p:dataTable value="#{tz.points.toArray()}" var="tpoint" id="tpointsTable" emptyMessage="">
<p:column headerText="point">
<p:outputLabel value="#{tpoint.description} #{tpoint.position}(m)"/>
</p:column>
<p:column headerText="#{mesureController.varValues['typeMesure']}">
<p:panelGrid columns="3" layout="grid">
<p:outputLabel value="#{tpoint.temperature.minTemperature}" title="min temperature"
rendered="#{mesureController.selectedTypeMesure.name().equals('TEMPERATURE')}"/>
<p:outputLabel value="#{tpoint.epaisseur.minEpaisseur}" title="min epaisseur"
rendered="#{mesureController.selectedTypeMesure.name().equals('EPAISSEUR')}"/>
<p:inputText value="#{mesureController.currentMesure.tadDetails[tpoint]}"
converter="javax.faces.Double" converterMessage="valeur numerique"
style="width: 50px">
<p:ajax event="change" update=":iwFormsForm"
listener="#{mesureController.validateMesureTADValue}"/>
</p:inputText>
<p:outputLabel value="#{tpoint.temperature.maxTemperature}" title="max temperature"
rendered="#{mesureController.selectedTypeMesure.name().equals('TEMPERATURE')}"/>
<p:outputLabel value="#{tpoint.epaisseur.maxEpaisseur}" title="max epaisseur"
rendered="#{mesureController.selectedTypeMesure.name().equals('EPAISSEUR')}"/>
</p:panelGrid>
</p:column>
</p:dataTable>
</p:tab>
</p:accordionPanel>
<p:panel toggleable="true" header="Validation des mesures" rendered="#{mesureController.isValidationMesures()}">
<p:panelGrid id="tmp_validation2" columns="2" class="Wid100">
<h:outputLabel value="Valider les mesure *"/>
<p:selectOneMenu value="#{mesureController.varValues['valider_les_mesures']}" required="true">
<f:selectItem itemLabel="Sélectionner" itemValue="#{null}"/>
<f:selectItem itemLabel="Oui" itemValue="Oui"/>
<f:selectItem itemLabel="Non" itemValue="Non"/>
<p:ajax event="change" process="@this"/>
</p:selectOneMenu>
</p:panelGrid>
</p:panel>
</p:panel>
所以我需要知道如何解决这个问题,以便保持面板的顺序与 html 中的顺序相同。
面板及其 'order' 来自
value="#{mesureController.structureComposants.toArray()}"
这不是 PrimeFaces,也不是 java-ee,也不是 java,而是 EL(所以标记有点像 'wrong')。但实际上,EL 是对象字段上的 toArray()
。所以您可以(应该)创建一个简单的单元测试并查看它在普通 java 中的作用。
那么您会以 99.999% 的把握看到顺序也是 'random',使这个问题成为一个纯粹的 java 问题。实际上,无法保证 Set 中的顺序,因为它取决于实现(OrderedSet 是,其他可能不是)
因此,直接使用 OrderedSet
或(实现)Array
(例如 ArrayList
)将 'fix' 这个问题
另见
Is a set's "toArray" deterministic?
面板及其 'order' 来自
value="#{mesureController.structureComposants.toArray()}"
因为要修复它,您必须使用此值创建一个新的 属性 但已排序。例如,如果您的变量 structureComposants 是一个 Set,您可以尝试以下操作。
List<Entity> structureComposantsList = structureComposants.stream().collect(Collectors.toList());
Collections.sort(structureComposantsList, (o1, o2) -> o1.getAttribute1().compareTo(o2.getAttribute1()));
注意:为您的class更改实体class并在您的@PostContruct方法中初始化
最后,在您的代码中使用变量 structureComposantsList 作为
value="#{mesureController.structureComposantsList}"
我在 Primefaces 中使用 accordionPanel。当我刷新页面时,顺序改变了!例如:我有 1,2,3 然后它们变成 2,3,1 或 3,2,1!每次刷新页面时面板的顺序都会改变!
<p:panel toggleable="true" header="Mesure" rendered="#{not empty mesureController.varValues['structure']}">
<p:accordionPanel value="#{mesureController.structureComposants.toArray()}" var="sc">
<p:tab title="#{sc.nomComposant}" closable="false">
<p:dataTable value="#{sc.plans.toArray()}" var="plan" id="plansTable" emptyMessage="">
<p:column headerText="Plan">
<p:outputLabel value="#{plan.nomPlan}"/>
</p:column>
<p:column headerText="Image">
<p:lightBox styleClass="imagebox" id="lighbox1"
rendered="#{not empty plan.image}">
<h:outputLink
value="data:image/png;base64,#{ligneBean.getImageContentsAsBase64(plan)}"
title="#{plan.commentaire}">
<img src="data:image/png;base64,#{ligneBean.getImageContentsAsBase64(plan)}"
style="height: 120px; width: auto; margin-right: 10px;"/>
</h:outputLink>
</p:lightBox>
</p:column>
<p:column headerText="#{mesureController.varValues['typeMesure']}">
<ui:repeat value="#{plan.reperes.toArray()}" var="repere">
<p:panelGrid columns="5" layout="grid">
<p:outputLabel id="nom_repere" value="#{repere.nomRepere}"/>
<p:tooltip id="toolTipGrow" for="nom_repere" value="#{repere.commentaire}"
position="left"/>
<p:outputLabel value="#{repere.repereConfig.temperature.minTemperature}"
title="min temperature"
rendered="#{mesureController.selectedTypeMesure.name().equals('TEMPERATURE')}"/>
<p:outputLabel value="#{repere.repereConfig.epaisseur.minEpaisseur}"
title="min epaisseur"
rendered="#{mesureController.selectedTypeMesure.name().equals('EPAISSEUR')}"/>
<p:inputText value="#{mesureController.currentMesure.structureDetails[repere]}"
disabled="#{not mesureController.firstTask}"
converter="javax.faces.Double" converterMessage="valeur numerique"
style="width: 50px">
<p:ajax event="change" listener="#{mesureController.validateMesureValue}"
update=":iwFormsForm">
</p:ajax>
</p:inputText>
<p:outputLabel value="#{repere.repereConfig.temperature.maxTemperature}"
title="max temperature"
rendered="#{mesureController.selectedTypeMesure.name().equals('TEMPERATURE')}"/>
<p:outputLabel value="#{repere.repereConfig.epaisseur.maxEpaisseur}"
title="max epaisseur"
rendered="#{mesureController.selectedTypeMesure.name().equals('EPAISSEUR')}"/>
</p:panelGrid>
</ui:repeat>
</p:column>
</p:dataTable>
</p:tab>
</p:accordionPanel>
<ui:fragment rendered="#{mesureController.typeStructure.equals('FOUR')}">
<ui:include src="graph.xhtml"/>
</ui:fragment>
<p:accordionPanel value="#{mesureController.fourZones.toArray()}" var="fz" activeIndex="0,1,2,3,4,5">
<p:tab title="#{fz.description}">
<p:dataTable value="#{fz.points.toArray()}" var="fpoint" id="fpointsTable" emptyMessage="" >
<p:column headerText="point">
<p:outputLabel value="#{fpoint.description} #{fpoint.position}(m)"/>
</p:column>
<p:column headerText="#{mesureController.varValues['typeMesure']}">
<p:panelGrid columns="3" layout="grid">
<p:outputLabel value="#{fpoint.temperature.minTemperature}" title="min temperature"
rendered="#{mesureController.selectedTypeMesure.name().equals('TEMPERATURE')}"/>
<p:outputLabel value="#{fpoint.epaisseur.minEpaisseur}" title="min epaisseur"
rendered="#{mesureController.selectedTypeMesure.name().equals('EPAISSEUR')}"/>
<p:inputText value="#{mesureController.currentMesure.fourDetails[fpoint]}"
converter="javax.faces.Double" converterMessage="valeur numerique"
style="width: 50px">
<p:ajax event="change" update=":iwFormsForm"
listener="#{mesureController.validateMesureFourValue}"/>
</p:inputText>
<p:outputLabel value="#{fpoint.temperature.maxTemperature}" title="max temperature"
rendered="#{mesureController.selectedTypeMesure.name().equals('TEMPERATURE')}"/>
<p:outputLabel value="#{fpoint.epaisseur.maxEpaisseur}" title="max epaisseur"
rendered="#{mesureController.selectedTypeMesure.name().equals('EPAISSEUR')}"/>
</p:panelGrid>
</p:column>
</p:dataTable>
</p:tab>
</p:accordionPanel>
<p:accordionPanel value="#{mesureController.tadZones.toArray()}" var="tz">
<p:tab title="#{tz.description}">
<p:dataTable value="#{tz.points.toArray()}" var="tpoint" id="tpointsTable" emptyMessage="">
<p:column headerText="point">
<p:outputLabel value="#{tpoint.description} #{tpoint.position}(m)"/>
</p:column>
<p:column headerText="#{mesureController.varValues['typeMesure']}">
<p:panelGrid columns="3" layout="grid">
<p:outputLabel value="#{tpoint.temperature.minTemperature}" title="min temperature"
rendered="#{mesureController.selectedTypeMesure.name().equals('TEMPERATURE')}"/>
<p:outputLabel value="#{tpoint.epaisseur.minEpaisseur}" title="min epaisseur"
rendered="#{mesureController.selectedTypeMesure.name().equals('EPAISSEUR')}"/>
<p:inputText value="#{mesureController.currentMesure.tadDetails[tpoint]}"
converter="javax.faces.Double" converterMessage="valeur numerique"
style="width: 50px">
<p:ajax event="change" update=":iwFormsForm"
listener="#{mesureController.validateMesureTADValue}"/>
</p:inputText>
<p:outputLabel value="#{tpoint.temperature.maxTemperature}" title="max temperature"
rendered="#{mesureController.selectedTypeMesure.name().equals('TEMPERATURE')}"/>
<p:outputLabel value="#{tpoint.epaisseur.maxEpaisseur}" title="max epaisseur"
rendered="#{mesureController.selectedTypeMesure.name().equals('EPAISSEUR')}"/>
</p:panelGrid>
</p:column>
</p:dataTable>
</p:tab>
</p:accordionPanel>
<p:panel toggleable="true" header="Validation des mesures" rendered="#{mesureController.isValidationMesures()}">
<p:panelGrid id="tmp_validation2" columns="2" class="Wid100">
<h:outputLabel value="Valider les mesure *"/>
<p:selectOneMenu value="#{mesureController.varValues['valider_les_mesures']}" required="true">
<f:selectItem itemLabel="Sélectionner" itemValue="#{null}"/>
<f:selectItem itemLabel="Oui" itemValue="Oui"/>
<f:selectItem itemLabel="Non" itemValue="Non"/>
<p:ajax event="change" process="@this"/>
</p:selectOneMenu>
</p:panelGrid>
</p:panel>
</p:panel>
所以我需要知道如何解决这个问题,以便保持面板的顺序与 html 中的顺序相同。
面板及其 'order' 来自
value="#{mesureController.structureComposants.toArray()}"
这不是 PrimeFaces,也不是 java-ee,也不是 java,而是 EL(所以标记有点像 'wrong')。但实际上,EL 是对象字段上的 toArray()
。所以您可以(应该)创建一个简单的单元测试并查看它在普通 java 中的作用。
那么您会以 99.999% 的把握看到顺序也是 'random',使这个问题成为一个纯粹的 java 问题。实际上,无法保证 Set 中的顺序,因为它取决于实现(OrderedSet 是,其他可能不是)
因此,直接使用 OrderedSet
或(实现)Array
(例如 ArrayList
)将 'fix' 这个问题
另见
Is a set's "toArray" deterministic?
面板及其 'order' 来自
value="#{mesureController.structureComposants.toArray()}"
因为要修复它,您必须使用此值创建一个新的 属性 但已排序。例如,如果您的变量 structureComposants 是一个 Set,您可以尝试以下操作。
List<Entity> structureComposantsList = structureComposants.stream().collect(Collectors.toList());
Collections.sort(structureComposantsList, (o1, o2) -> o1.getAttribute1().compareTo(o2.getAttribute1()));
注意:为您的class更改实体class并在您的@PostContruct方法中初始化
最后,在您的代码中使用变量 structureComposantsList 作为
value="#{mesureController.structureComposantsList}"