1

I'm trying to create a customized version of the campaign hierarchy page, allowing for the display of additional data other than just campaign names. I have a Map<ID, List<Campaign>> keyed with the ID of a parent campaign and valued with a list of direct child campaigns of the keyed parent. There is one null key in the map that correlates to a list with only one element, that element being the root campaign from which the hierarchy begins. The assumption can be made that every campaign represented in one of the value lists is also represented as a key, which may or may not correlate to an empty list (depending on whether that campaign has any direct children).

Here's a simple, concrete example of the map described above:

{
  null=>(Campaign:{Name=Parent, Id=701180000000luvAAA})
  701180000000luvAAA=>(Campaign:{Name=Child 1, Id=701180000000luwAAA}, Campaign:{Name=Child 2, Id=701180000000luxAAA})
  701180000000luwAAA=>(Campaign:{Name=Grandchild, Id=701180000000luyAAA})
  701180000000luxAAA=>()
  701180000000luyAAA=>()
}

Given that map, I have a recursive method that traverses down each line of descendants beginning with the root (imagine the pre-order navigation of a tree structure):

// Populated campaign map
private Map<ID, List<Campaign>> campaignsByParent;

public void displayCampaignsRecursively(ID parentId) {
    List<Campaign> childCampaigns = this.campaignsByParent.get(parentId);
    for (Campaign c : childCampaigns) {
        // Display campaign here
        this.displayCampaignsRecursively(c.Id);
    }
}

which I can call like:

// Root campaign does not have a parent, so parent ID is null to start.
ID rootCampaignParentId = null;
Controller.displayCampaignsRecursively(rootCampaignParentId);

The problem is I'm not sure how to actually display the campaigns. I want to display the data in an <apex:pageBlock>, but I know I can't just bind the map to an <apex:repeat> control since the order of elements can change. How can I do this? Any and all ideas are appreciated!

2 Answers 2

1

I've been wanting to respond to this post. I think you have an interesting problem to solve from a mathematical standpoint. See the image below which better illustrates how I see your issue and most of what I'd like to address.

Hierarchy from Root Campaign

As the above illustrates, you don't know until composition time, how many children, grandchildren, great-grandchildren, etc that you'll have. As a result, fitting them across the screen could be problematic.

If we look at an HTML page from a block standpoint, each box in the image above can be considered a "block element" that could be represented by a <div> and a closing <\div>. Similarly, each row in the image could be viewed the same as could combinations of rows.

As you can see, the great-grand children would have been 11 block elements wide had I attempted to put all of them on the same row while the previous row was only 6 elements wide. These types of diagrams by their very nature tend to only get wider and wider.

Instead of making the chart wider, I opted instead to break up the rows the related GGC (great-grand children) were on. You'll notice that C3GGC1, the first child of Grandchild 4 (C3GC1) couldn't be lined up directly underneath it's parent's box. I did this intentionally to point out that most any algorithm you come up with might be "stupid" at times and this could likely happen. Solving this problem is the part that will make this challenging to solve while obtaining an aesthetically pleasing result.

It seems to me that you'll need to determine how many "nodes" you have to contend with - places where you'll need to break up your rows of blocks at each "sub-level". I'd recommend planning on needing to put each grandchild and below on a separate row of it's own, then test to see if it can be moved up; using an iterative approach along those those lines for each level in your hierarchy. After x number of iterations, accept your "best" results and move on to the next level below.

I'd also recommend you consider using jquery to create your blocks because it will allow you to easily insert block elements dynamically into the Dom. Presumably, you could also pass arguments from your controller to either your JS or JQ code using JS remoting to tell it how to set up the document layout and bindings.

Its an interesting challenge that unfortunately I'm not able to spend time writing or locating code that might be of use to you in sorting this out further.

1
  • Stellar effort. Wow.
    – Adrian Larson
    Mar 31, 2015 at 23:39
0

You can put the campaign records in a 2d array of campaign records. Before calling the display method recursively, you can add the elements in an array hierarchically and this array can be used in data table on a page.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .