20

I have a Visualforce page with two controller extensions. Is there any way to get a reference to one of the extensions in the other one?

  • Thanks for your reply. Unfortunately this doesn't help me. Both of my classes are already instantiated (because they are both controller extensions for the same page). I need to change one of the instance variables in one of the extensions from the other one. – rael_kid Jul 1 '13 at 11:49
  • What's the use case? I have a solution that works for limited data transfer, but if it doesn't help you, I don't want to clutter this question with useless responses. – sfdcfox Jul 1 '13 at 11:58
  • Basically both of the controllers contain lots of (independent) logic and one (only one) of the Boolean variables in one of the controllers is set to false or true from one of the functions in the other controller extension. – rael_kid Jul 1 '13 at 12:10
15

You can't directly reference the other classes (extensions) in the same page, but you can make variables static, assuming they participate in the form; this requirement exists because static variables are transient (do not serialize into the view state). Simple example follows:

Page:

<apex:page standardController="Account" extensions="ext1,ext2">
<apex:form >
    <apex:inputText value="{!message}"/>
    <apex:outputText value="{!ext1message}"/>
</apex:form>
</apex:page>

Ext1:

public with sharing class ext1 {
    public static string message { get; set; }

    public ext1(ApexPages.StandardController controller) {

    }
}

Ext2:

public with sharing class ext2 {

public ext2(ApexPages.StandardController controller) {

}

public string getext1message() {
    return ext1.message;
}
}

When you type a message and press Enter, it will be echoed back from ext2's getExt1Message() function. As you can see, you can use static variables. The caveat is that message is bound to a form element, and will be submitted each time the page posts. Without the apex:inputText element, this code wouldn't work.

Since your comments specify that it is a boolean value that is calculated, you should probably store the results of the value into an apex:inputHidden element so that the form will correctly pass the value between extensions.

| improve this answer | |
5

This week I needed to reference once controller from another and ended up using this code:

public with sharing class Ext1 {
    private Registry r;
    public Ext1(ApexPages.StandardController sc) {
        r = Registry.instance();
        r.add(Ext1.class, this);
        ...
    }
    private Ext2 getExt2() {
        return (Ext2) r.get(Ext2.class);
    }
}

public with sharing class Ext2 {
    private Registry r;
    public Ext2(ApexPages.StandardController sc) {
        r = Registry.instance();
        r.add(Ext2.class, this);
        ...
    }
    private Ext1 getExt2() {
        return (Ext1) r.get(Ext1.class);
    }
}

with this singleton:

public class Registry {
    private static Registry instance;
    private Map<Type, Object> m = new Map<Type, Object>();
    // Set a view state field to this
    public static Registry instance() {
        if (instance == null) instance = new Registry();
        return instance;
    }
    // Singleton
    private Registry() {
    }
    public void add(Type key, Object value) {
        m.put(key, value);
    }
    public Object get(Type key) {
        return m.get(key);
    }
}

When the extensions are constructed, they are added (registered) into a singleton (static) instance. But a reference to that singleton is also made a field in each extension ensuring that the extension references are made part of the view state. So the cross-references are preserved across form posts etc.

| improve this answer | |
0

That's kind of a hokey workaround.
The only real way to solve this is for Salesforce to add a method for VF pages to return the instantiated Controller.

In the meantime, just add a class and instantiate it inside your extension. When your page needs to display fields from the related class, you just have to include the new round of indirection.

| improve this answer | |

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.