3
<apex:repeat value="{!blocksThatAreComponents}" var="key">
     <div id="{!key}">                   
           <apex:dynamicComponent componentValue="{!PageComponentsMap[key]}" />    
      </div>
</apex:repeat>

I am trying to use apex:repeat and display a number of dynamic components. Problem is the key variable in {!PageComponentsMap[key]} evaluates to null for reasons I do not understand. On the div, it evaluates well but not on the dynamic component.

If I change {!PageComponentsMap[key]} to {!PageComponentsMap['somekey']} where (key == 'somekey'), it works.

I found out that due to visualforce page execution order, dynamic components are rendered first before any other thing on the page so by the time they are rendered, key is null. To solve that, I set the invokeAfterAction attribute of dynamic component to true.

<apex:repeat  value="{!pageComponents}" var="pc">           
       <span>{!pc}</span>
        <apex:dynamicComponent invokeAfterAction="true"  componentValue="{!pc}"/>
 </apex:repeat>

That way the other things in the page are rendered before the dynamicComponent. Problem with this is that it uses the last value of pc for all the components which means that it renders the same thing many times

public class getPageContent {        
    public List<ApexPages.Component> pageComponents { get; set; }   

    public getPageContent() {         

        pageComponents = new List<ApexPages.Component>();
        pageComponents.add(new Component.c.GSCMS_ChatterFeed());
        pageComponents.add(new Component.c.GSCMS_SVGExample());
        pageComponents.add(new Component.c.SampleComponent());            
    }         
}    

How do I make it use the different values of pc that I have

Update to the question : Though there are distinct values of Page components it renders only the last added component as below.

enter image description here

  • can you paste your complete controller, component and page – Rao Oct 9 '14 at 15:35
  • @rao Right now I have a different problem. I set the invokeAfterAction attribute to true and since the page execution changed, my problem was partially solved but the new issue I have now is that it renders the last value of map multiple times since after page load variable key is set tot the last value – Yanki Twizzy Oct 9 '14 at 17:26
  • can you update the question and post your controller, page and complete component – Rao Oct 9 '14 at 17:31
  • @rao I have updated the question – Yanki Twizzy Oct 9 '14 at 17:48
  • I am able to replicate your problem in my org too, I see that the repeat is giving distinct Id's but when feed to the dynamic component it just takes only the last val of the apexcomponent Id. – Rao Oct 9 '14 at 20:50
1

I have this same problem and I came here hoping for a simple fix. No luck.

I will share what I intend to do to solve it. It's not elegant and it won't fit every scenario but I expect it to get the job done. I'll be sure to report back here with specifics when I'm done.

Problem Recap

If you don't use invokeAfterAction="true", nothing shows up in time because it's not initialized. If you do use it, the page doesn't properly repeat through your collection and every instance is a duplicate of one of your collection items.

My Solution

I'm going to stitch the components together inside my Apex and deliver it to the page as a single dynamicComponent with invokeAfterAction="true".

In other words, the collection that I am repeating over I will instead iterate through in Apex code and build a single dynamicComponent that contains a child instance of ApexPages.Component for each item in my collection.

If you are doing clever and complex things inside your <apex:repeat> this approach could be a real pain. At a minimum I have to take other normal markup I had inside my <apex:repeat> and turn it into extra components.

I understand why dynamicComponents have some weird edge case behavior, and honestly I pretty much expected it wouldn't work inside an <apex:repeat>. Was hoping though.

Update

This strategy ended up working fine, I combine my individual components in my apex controller before serving them to the visualforce page.

It also doesn't seem to matter if I use invokeAfterAction="true" or not, both render correctly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.