I'm trying to display a chronological list of CaseHistory records to display case edits. I have the following code:

public Map<CaseHistory,String> getHelpdeskHistory() {

    List<CaseHistory> historyList = new List<CaseHistory>();

    historyList = [SELECT Case.Subject , CreatedById, OldValue, NewValue, Field, CreatedDate  FROM CaseHistory ORDER BY CreatedDate DESC];

    Map<CaseHistory, String> mapCaseToEditor = new Map<CaseHistory,String>();

    for(CaseHistory ch: historyList){

            User caseEditor = new User();

            caseEditor = [select Name from User where id = :ch.CreatedById];

            mapCaseToEditor.put(ch, caseEditor.Name);


    return mapCaseToEditor;

The CreatedById is the ID of the user who edited a case. I'm retrieving them ordered by CreatedDate, but I need to attach a name to display it on my visualforce page.

However, due to the map being unordered, I can't figure out a better way to preserve the order returned by the query. This is how I display it in the VF page:

<apex:repeat value="{!HelpdeskHistory}" var="C">
     {!HelpdeskHistory[C]} edited {!C.Field}

This works and displays the person who edited the case, but it's not in CreatedDate order. Is there any way I can attach a name to an ordered list and display it in VF?


1 Answer 1


Let me clarify a few things here:

  • Don't write SOQL queries inside a for loop
  • You can get related fields from the user [CreatedBy.Name]
  • If you want to preserve the order of elements in your map, you'll need to keep an index as a key (or other primitive type)
  • You can have all your data in a wrapper class mapped to an index

So your code should look something like this:

public class CaseHistoryWrapper
    public String field {get; set;}
    public String editedBy {get; set;}

    public CaseHistoryWrapper(String field, String editedBy)
        this.field = field;
        this.editedBy = editedBy;

public Map <Integer, CaseHistoryWrapper> getHelpdeskHistory()
    Map <Integer, CaseHistoryWrapper> result = new Map <Integer, CaseHistoryWrapper> ();

    Integer index = 0;

    for (CaseHistory caseHistory : [SELECT Case.Field, CreatedBy.Name FROM CaseHistory ORDER BY CreatedDate DESC])
        result.put(index, new CaseHistoryWrapper(caseHistory.Case.Field, caseHistory.CreatedBy.Name));

    return result;

Then in your VF you iterate through the keys of the map (indexes) and you can easily reference all the data corresponding to a specific index:

<apex:repeat value="{!HelpdeskHistory}" var="index">
    {!HelpdeskHistory[index].editedBy} edited {!HelpdeskHistory[index].field}

Disclaimer: I wrote this code on the fly and it might not 100% work, but this is the approach I would be taking to solve this problem.


You must log in to answer this question.