Find your content:

Search form

You are here

Loading a custom component into a Visualforce page dynamically

 
Share

I have a visualforce page that I would like to inject custom components (header and footer) if they exist into the page.

According to the docs Creating and Displaying Dynamic Components I can instantiate a custom component like so

Component.c.MyCustomComponent myDy = new Component.c.MyCustomComponent();

but I don't know the name of MyCustomComponent ahead of time, and as mentioned it may not exist. Is there an equivalent of something like:

Component myDy = Type.forName('c:MyCustomComponent'); //does not compile ;)

I am not tied to dynamic visualforce, If anyone knows of an alternative solution I would be very interested.


Attribution to: Daniel Blackhall

Possible Suggestion/Solution #1

I have developed a solution, there are shortcomings that I hope someone knows the solution too. The following code snippet allows loading of a visualforce component onto a page dynamically.

public class MyController {

    public transient ApexPages.Component headerComponent { get; private set; }

    public MyController() {
        Type t = Type.forName('Component.c.MyCustomComponent');
        if(t != null) {
            this.headerComponent = (ApexPages.Component)t.newInstance();
        }
    }
}

.

<apex:dynamicComponent componentValue="{!headerComponent}" />

The shortcoming is that, so far as I can tell parameters can not be passed. I would be happy to be proved wrong on this point :)

Credit goes to @Peter for steering me in the right direction on this.


Attribution to: Daniel Blackhall

Possible Suggestion/Solution #2

I wanted to follow up on this even though its from last year since this was one of the first pages I found when searching.

visual force page with a dynamic component

<apex:page id="thePage">
  <apex:form id = "theForm">
    <apex:dynamicComponent componentValue="{!myCustomComponent}"/>
  </apex:form>
</apex:page>

controller

public class My_Custom_Controller {

  public Account myAccount {get;set;}

  public My_Custopm_Controller() {

    // initialized account logic
  }

  public ApexPages.Component getMyCustomComponent() {
    Component.c.My_Custom_Component customComponent =
      new Component.c.My_Custom_Component(param1=myAccount, param2='My String');

    return customComponent;
  }
}

Notice in the constructor for the component you can set parameters by using key=value pairs.

Component:

<apex:component>
  <apex:attribute name="param1" type="Account" />
  <apex:attribute name="param2" type="String" />

  <!-- The rest of my component -->
</apex:component>

The issue with this however is that this component is no longer kept int he view state. So if have an apex:actionFunction and that calls a method that returns a null page reference this component would get reinitialized if it is sitting inside a panel that you have set as the rerender on the action function.

Assume my component had an inputField for an Account field. If the user had entered anything into that field that has yet to be committed that data would be lost.

I'm currently toying with the idea of on any of my actionFunctions running through the form and storing all the data and storing it in possibly a json string and in the onComplete reset everything.


Attribution to: Pick

Possible Suggestion/Solution #3

I'm just learning about the Type class, but looking at the docs, I would think the syntax you would want to use is:

Type.forName('Component.c.MyCustomComponent');

But as I play with this more, I think the greater problem is what to pass it into.

Component, is either not a concrete class, or Apex is not given access to it.

The docs explicitly state that apex:component is not represented in dynamic Apex. So no dice there. Still, I tried: Component.Apex myComp; (seemed to confuse the hell out of the compiler) Component.Apex.Component; (invalid type)

Finally, this compiles, but throws a null pointer exception:

Type t = Type.forName('Component.c.MyCustomComponent'); Object myComp = (Object) t.newInstance();

And Object, while it exists, probably won't bind to your page, in the end.

I think you've reached one of the limits of the platform, unfortunately.


Attribution to: pchittum
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/3414

My Block Status

My Block Content