在重复控件内重复控制:哈希图似乎被覆盖

时间:2012-05-11 01:27:37

标签: xpages

我有一个外部重复控件,它将它的集合作为一个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();    
}

1 个答案:

答案 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
}

希望有所帮助