+ Start a Discussion
sfdcsushilsfdcsushil 

Reloading Apex Component in the page

Hi,

 

We have an Apex Component(has one Controller attached to it) included in the Visualforce page. We want to get it refreshed when one User lookup is populated on the Visualforce Page. Please suggest if there is a way to accomplish this.

We had tried page reload. But that leads to Data being blanked out on the page. Is there any clean way to do it?

 

bob_buzzardbob_buzzard

If the data is blanked out that sounds like you aren't saving the information on the page. If you refresh the page or any part of it, that will regenerate based on the information stored in the controller(s).  Are you trying to pull back information from the related object tied to the lookup?

imranrazaimranraza

Hi Sushil,

you can try to palce your page component in outputpanel and then relaod the outputpanel, the component will be relaoded as outputpanel well be load.

Thanks

sfdcsushilsfdcsushil

Hi Imran/Bob,

 

I want only component code to get refreshed. For that i want to call Apex method written in the Component controller. But i am not able to call that method from the page as the page has different controller.

 

Also Imran, what do you mean by reloading output panel? does it mean rerender it after ajax call?

bob_buzzardbob_buzzard

Can you explain a little more about what you are trying to achieve. 

sfdcsushilsfdcsushil

I have one apex component(with some java script code) which refers to one Apex Controller.

I am refering above component in my page

 

<Apex:outputpanel>

<C:ComponentName someparameters>

<Apex:outputpanel>

 

When one field changes on the visualforce page, i want this Component to get refreshed. That is it should make one ajax call to the Component controller method.

 

But problem is in page i cannot refer to Component controller method. Also i cannot place ajax call in the component as it does not have Apex:page tags.

 

hope u understood my issue. Let me know if you need more information.

 

bob_buzzardbob_buzzard

Hmm. Could you pass the some the page controller to the component as an attribute, and then have the component controller "register" itself with the page controller?

sfdcsushilsfdcsushil

Thanks Bob for taking time in Helping me.

Can you Please let me know what do you mean by registering here?

And how do i call the Component controller this way and reload the component. 

bob_buzzardbob_buzzard

Can you tell us what it is you are trying to achieve from a functionalty perspective - this seems a somewhat torturous route to go and there might be other options.

sfdcsushilsfdcsushil
Thanks for ur help. I solved my problem some other way.
S@kh!S@kh!
@Sushil - please let us the solution here, i am facing the same issue. Thanks a ton in advance
S@kh!S@kh!

@Sushil - Please let us know the solution, i m facing exactly the same issue. Thanks in advance

Franco PriggioneFranco Priggione
Hello @sfdcsushil,iit seems that you were trying to solve the situation you had but giving the minimum information for some reason. Then you say you solved it some other way, but you say nothing about how you sorted it out (even when someone else asked you how and in a very polite way). The idea of this forum/community is to share knowledge so we can all be benefit from it. If you seek help, you should help others too.
sfdcsushilsfdcsushil
My apologies. I should have added the solution. Also I completely missed above post asking for solution. It's been many years, so I am not sure how I handled it.
Chris_NChris_N
Hi everyone. I came across this post while searching for a solution to a similar problem. I'll go ahead and post what I have in case anyone else gets stuck.

I needed to get specific components to re-render within a visualforce page. I found a solution by making the page controller aware of its component controllers. Once the visualforce page was aware of additional component controller methods, I was able to force the component to refresh itself. Here’s a walkthrough with a simplified sample of what I did. I’ll also list the source I used to create this solution. (You can use this in your dev org if you'd like to try it out, you'll just need to add some fields to the user record)
  • Create your Page virtual classes. Your page controller and component controller will need separate virtual classes that they will extend. Think of this as a framework that allows them to communicate.
    • Create the virtual class for your page controller. This will contain various getters/setters for the component controllers associated with this page controller. (See the snippet below)
    • public virtual class PageControllerBase{
      //This is an extension to the PARENT controller.
          
          private ComponentControllerBase myComponentController;
          //a map to interact with multiple components (children)
          private Map<String, ComponentControllerBase> componentControllerMap;
          
          public virtual ComponentControllerBase getMyComponentController() {
              return myComponentController;
          }
          
          //getter for multiple components (children)
          public virtual Map<String, ComponentControllerBase> getMyComponentControllerMap() {
              return componentControllerMap;
          }
          
          public virtual void setComponentController(componentControllerBase cController) {
              myComponentController = cController;
          }
          
          //setter for multiple components (aka children, with a key to the controller)
          public virtual void setcomponentControllerMap(String key, componentControllerBase cController) {
              if (componentControllerMap == null) {
                  componentControllerMap = new Map<String, componentControllerBase>();
                  componentControllerMap.put(key, cController);
              }
              else {
                  componentControllerMap.put(key, cController);
              }
          }
          
          public PageControllerBase getThis() {
              return this;
          }   
      }
    • Create the virtual class for your component controller. This will contain a get/set for the key, and page controller that invoked the component. These will be set as attributes when the component is created. (See the snippet below)
    • public virtual class ComponentControllerBase {
          
          //For key/pagecontroller pairs
          public String key {
              get;
              set {
                  if (value != null) {
                      key = value;
                      if (pageController != null) {
                          pageController.setComponentControllerMap(key, this);
                      }
                  }
              }
          }
      
          public pageControllerBase pageController {
              get;
              set {
                  if (value != null) {
                      pageController = value;
                      pageController.setComponentController(this);
                  }
              }
          }
      }
      
  • Create component/controller and page/controller. Once they each extend their respective virtual classes, they can communicate with each other.
    • Create the component controller. The component below is meant to set checkboxes on the user record. Pay special attention to the structure of the getUser method. A check is made for a null user. If no user is found, the init method is called. Calling init will force the component to re-render. Keep this in mind for later. (See the snippet below)
    • public class MyComponentController extends ComponentControllerBase {
      	public User user;
      	public Id userId;
      
      	//Getters/Setters
      	public Id getUserId() {
      		return userId;
      	}
      
      	public void setUserId(Id i) {
      		userId = i;
      	}
      
      	public User getUser() {
      		if (user == null) {
      			init(userId);
      		}
      		return user;
      	}
      
      	public void setUser(User u) {
      		user = u;
      	}
      
      	public void saveUser() {
      		update user;
      	}
      
      	//Initialize OR *Re-Initialize* this component. This is the key to a refresh/re-render. A query is made and The setters are recalled.
      	public void init(Id uId) {
      		User u = queryForUserSettings(uId);
      		setUser(u);
      		//setNotificationBooleans(u);
      	}
      
      	private User queryForUserSettings(Id uId) {
      		return [select Id, 
      					Receives_Weekly_Digest__c, 
      					New_Offer_Notifications__c
      				from User
      				where Id = :uId limit 1];
      	}
      }
    • Create the component. Note the attributes being set, mainly the key and pagecontroller attributes. (See the snippet below)
    • <apex:component controller="MyComponentController" allowDML="true">
        
      	<h1>Contact Settings Component</h1>
      	<div>
      		<apex:attribute name="keyAssigned"
                                      type="String"
                                      assignTo="{!key}"
                                      description="The key given to this component so the page can easliy get access to it." />
      
              <apex:attribute name="PageControllerBaseCalling" 
                                type="PageControllerBase" 
                                assignTo="{!pageController}" 
                                description="The controller for the page." />
      
              <apex:attribute name="usrId" 
              				description="Relevant User." 
              				type="Id" assignTo="{!userId}" 
              				required="true"/>
      
              <form>
      		  	<apex:outputPanel>
      		  		<li>	
      		  			Receives weekly digest&nbsp;<apex:inputcheckbox value="{!User.Receives_Weekly_Digest__c}"/> 
      		  			New offer notifications&nbsp;<apex:inputcheckbox value="{!User.New_Offer_Notifications__c}"/>
      		  		</li>
      			</apex:outputPanel>
      		</form>
      	</div>
      </apex:component>
    • Create the page controller. Notice the different save methods. Each method will refer to the save method on a specific component, which is found by its key. After saving the first component, the second component’s init method is called, which causes it to re-render. (See the snippet below)
    • public without sharing class MyPageController extends PageControllerBase {
      	public Id userId {get; set;} 
      	public MyComponentController componentOne {get; set;}
      	public MyComponentController componentTwo {get; set;}
      
      	public MyPageController() {
      		userId = UserInfo.getUserId();
      	}
      
      	public PageReference callComponentOneSaveUser() {
      		System.debug('Saving the first component');
      		componentOne = (MyComponentController) getMyComponentControllerMap().get('ComponentOne');
      		componentOne.saveUser();
      
      		//force the second component to re-render!
      		componentTwo = (MyComponentController) getMyComponentControllerMap().get('ComponentTwo');
      		componentTwo.init(UserInfo.getUserId());
      		return null;
      	}
      
      	public PageReference callComponentTwoSaveUser() {
      		componentTwo = (MyComponentController) getMyComponentControllerMap().get('ComponentTwo');
      		componentTwo.saveUser();
      		return null;
      		//notice how there isn't an init call here. The first component will lag behind this one.
      	}
      }
    • Create the page. This page will display each component in sequence. Note the key that is assigned to each component, as well as the save method underneath each. (See the snippet below)
    • <apex:page controller="MyPageController">
      
      	<h1>Parent Page</h1>
      	<p>
        		This is the Parent page. This page will drive the actions of the child component.
        	</p>
        	<br/>
        	<br/>
      	<h2>First Component - Saving this will refresh the second component</h2>
      	<br/>
      
      	<apex:form >
      	  	<c:MyComponent PageControllerBaseCalling="{!this}" keyAssigned="ComponentOne" usrId="{!userId}"/>
      	  	<apex:commandLink action="{!callComponentOneSaveUser}" value="Save"/>
      	</apex:form>
      
      	  <br/>
      	  <h2>Second Component - Saving this will NOT refresh the first component</h2>
      	  <br/>
      
      	<apex:form >
      	  	<c:MyComponent PageControllerBaseCalling="{!this}" keyAssigned="ComponentTwo" usrId="{!userId}"/>  
      	  	<apex:commandLink action="{!callComponentTwoSaveUser}" value="Save"/>
      	</apex:form>  
      	
      </apex:page>
  • That's it. The most important things to remember here are...
    • Implement the right extension classes so your page controller can communicate with your component controllers.
    • Make sure your component controllers have an init method. This allows them to re-query and reset.
    • Call the init method for the right component controllers based on their key values that were assigned when they were created. This will make them re-render.
  • Many thanks to the authors of this technical library article. It covers page controller to component controller communication in general. https://developer.salesforce.com/page/Controller_Component_Communication