1

我有一个外部重复控件,将它的集合作为哈希图(变量名称是 hmOuterCollection)。在这个重复控件内部还有另一个重复控件,它也将它的集合作为哈希图(变量名称是 hmInnerCollection)。内部重复控件集合基于外部重复条目的键。发生的情况是,当我单击外部重复条目时,内部重复控制条目似乎覆盖了以前的条目。

例如,考虑以下

巴塞罗那(外部进入,点击第一)
梅西哈维 ·普约尔
曼联外部进入,点击第二) 鲁尼, xxx皇家马德里(外部进入,点击第三) 罗纳尔多· 卡卡







在我扩展所有这些足球队后,我返回并单击名为梅西的球员。它在服务器控制台上打印名字 Ronaldo。如果我单击名称 Xavi,它会打印 Kaka。

我只是想不通这里发生了什么。我也尝试了“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();    
}
4

1 回答 1

3

你的问题在这里:

 value="#{javascript:getPlayers(viewScope.teamID)}"

它应该读起来像:

 value="#{javascript:getPlayers(entryTeam.getKey())}"

外部变量在内部重复中可用。如果您将代码填充到范围对象中,它将引用其中的最后一个值。

请在 Java 代码中回收您的 Notes 对象。您还想去缓存 bean 中的值,因此您不需要每次都通读视图。最后,您可以从代码中消除 SSJS,只使用 EL -> 甚至更快

在 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可以处理Maps,你实际上只需要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
}

希望有帮助

于 2012-05-11T04:53:58.913 回答