我有一个外部重复控件,它将它的集合作为一个hashmap(变量名是hmOuterCollection)。在这个重复控件里面还有另一个重复控件,它将它的集合作为一个hashmap(变量名是hmInnerCollection)来获取。内部重复控件集合基于外部重复条目的键。发生的情况是,当我点击外部重复条目时,内部重复控制条目似乎会覆盖先前的条目。
例如,请考虑以下内容
巴塞罗那(外部条目,先点击)
梅西
哈维
普约尔
曼联(外部参赛,点击次数)
鲁尼,
XXX
皇家马德里(外部参赛,点击第三名)
罗纳尔多
卡卡
在我扩展了所有这些足球队之后,我回过头来点击名为梅西的球员。它在服务器控制台上输出名称Ronaldo。如果我点击名称Xavi,它会打印卡卡。
我只是想知道这里发生了什么。我也尝试了“repeatControls”和“removeRepeat”属性。没运气。这是一个java hashmap缓存还是重复控制行为有问题。
如果有人有任何想法,请告诉我。
这是XPage源
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.resources>
<xp:script src="/xpTestCacheIssue.jss" clientSide="false"></xp:script>
</xp:this.resources>
<xp:repeat id="repeat1" rows="30" value="#{javascript:getTeams()}"
var="entryTeam">
<xp:panel>
<xp:link escape="true"
text="#{javascript:entryTeam.getValue()}" id="lnkTeam">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="panelPlayers"
action="#{javascript:viewScope.teamID=entryTeam.getKey()}">
</xp:eventHandler>
</xp:link>
</xp:panel>
<xp:panel id="panelPlayers">
<xp:repeat id="repeat2" rows="30"
value="#{javascript:getPlayers(viewScope.teamID)}"
var="entryPlayer">
<xp:panel style="margin-left:20px;padding:10px">
<xp:link escape="true"
text="#{javascript:entryPlayer.getValue()}" id="lnkPlayer">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="selectedPlayer"
execMode="partial" execId="lnkPlayer">
<xp:this.action><![CDATA[#{javascript:viewScope.PlayerName=entryPlayer.getValue();}]]></xp:this.action>
</xp:eventHandler>
</xp:link>
</xp:panel>
</xp:repeat>
</xp:panel>
</xp:repeat>
<xp:panel id="selectedPlayer" style="border:1px solid green;padding:20px;background-color:yellow;font-weight:bold">
<xp:text escape="true" id="computedField1"
value="#{javascript:viewScope.PlayerName}">
</xp:text>
</xp:panel>
这是获取这些重复的哈希映射的java代码。有一个调用java方法的SSJS函数。
public Map<String,String> getSoccerTeams() {
Map<String,String> hmTeams=new HashMap<String,String>();
try {
ViewEntryCollection vec=vwTeams.getAllEntries();
ViewEntry ve=vec.getFirstEntry();
while (ve!=null) {
hmTeams.put(ve.getUniversalID(), ve.getDocument().getItemValueString("TeamName"));
ve=vec.getNextEntry(ve);
}
} catch (Exception e) {
e.printStackTrace();
}
return hmTeams;
}
public Map<String,String> getPlayers(String idPlayer) {
HashMap<String,String> hmPlayers=new HashMap<String,String>();
try {
View vwPlayers=this.dbCur.getView("playersview");
DocumentCollection dc=vwPlayers.getAllDocumentsByKey(idPlayer, true);
Document doc=dc.getFirstDocument();
while (doc!=null) {
hmPlayers.put(doc.getUniversalID(), doc.getItemValueString("PlayerName"));
doc=dc.getNextDocument(doc);
}
} catch (Exception e) {
e.printStackTrace();
}
return hmPlayers;
}
这是调用java方法的SSJS代码。
function getTeams() {
var Teams=new LoadTeams();
var hmTeams=Teams.getSoccerTeams();
return hmTeams.entrySet();
}
function getPlayers(playerID) {
var Teams=new LoadTeams();
var hmPlayers=Teams.getPlayers(playerID);
return hmPlayers.entrySet();
}
答案 0 :(得分:3)
你的问题在这里:
value="#{javascript:getPlayers(viewScope.teamID)}"
它应该读起来像:
value="#{javascript:getPlayers(entryTeam.getKey())}"
外部变量在内部重复中可用。如果将代码填充到范围对象中,它将引用其中的最后一个值。
请在Java代码中回收Notes对象。您还希望在bean中缓存值,因此您不需要每次都读取视图。最后,您可以从代码中消除SSJS并仅使用EL - &gt;更快
在EL上:
让我们假设您的Java类已注册为ManagedBean“ Soccer ”,您可以编写而不是:
<xp:repeat id="repeat1" rows="30" value="#{javascript:getTeams()}"
var="entryTeam">
这一个:
<xp:repeat id="repeat1" rows="30" value="#{Soccer.teams}"
var="entryTeam">
而不是:
<xp:repeat id="repeat2" rows="30"
value="#{javascript:getPlayers(entryTeam.getKey())}"
var="entryPlayer">
你写道:
<xp:repeat id="repeat2" rows="30"
value="#{Soccer.teams[entryTeam.key]}"
var="entryPlayer">
由于EL可以处理地图,因此您实际上只需要getTeams()
功能,不需要getPlayers()
功能。您希望稍微调整Java类以避免反复阅读视图:
public class SoccerHandler {
private Map<String,Collection<String>> allTheTeams = null;
public Map<String,String> getTeams() {
if (allTheTeams == null) {
this.loadTheTeams();
}
return allTheTeams;
}
private void loadTheTeams() {
// Add your own try/catch
this.allTheTeams = new HashMap<String,Collection<String>>();
View vwPlayers=this.getPlayersView(); // <-- Don't keep Notes objects in a BEAN
ViewEntryCollection vec=vwPlayers.getAllEntries();
String lastTeamName = "";
Collection<String> curTeam = null;
ViewEntry ve=vec.getFirstEntry();
while (ve!=null) {
Vector colVals = ve.getColumnValues();
String curTeamName = colVals.get(0); // 1st column = team
String curPlayerName = colVals.get(1); // 2nd column = player
if (!curTeamName.equals(lastTeamName)) { // New team found
if (curTeam != null) {
this.allTheTeams.put(lastTeamName, curTeam);
}
curTeam = new ArrayList<String>();
lastTeamName = curTeamName;
}
curTeam.put(curPlayerName);
ve=vec.getNextEntry(ve);
}
// Make sure we don't miss the last team
if (curTeam != null) {
this.allTheTeams.put(lastTeamName, curTeam);
}
ve.recycle();
vec.recyle();
}
// If you want to be able to force a re-read
public void reset() {
this.allTheTeams = null;
}
// more code here like getPlayerView that uses the resolver
}
希望有所帮助