Tuesday, June 18, 2013

Custom Component Controllers and using assignTo

So I have been working with components lately and have been pretty aggravated that I couldn't seem to get the assignTo to work correctly. So I followed the example showen in the documentation (Custom Component Controllers) word for word, and it worked.. but not really.  Once I tried switching the get/set to the way I prefer public String controllerValue {get; set;} it stopped working. I also noticed that if I was to put anything in the constructor it access it, it would create a null error. For example, if you were to use the same example as in the documentation and changed the class to:

public with sharing class sgf_ComponentAssignToIssue {

  public String controllerValue;
    
  public void setControllerValue (String s) {
    controllerValue = s.toUpperCase();
  }
    
  public String getControllerValue() {
    return controllerValue;
  }

  public sgf_ComponentAssignToIssue() {
    if (String.isNotBlank(controllerValue)) {
      controllerValue.toLowerCase();
      return;
    }
    ApexPages.addMessage(new ApexPages.Message(
      ApexPages.Severity.ERROR, 
      'string is blank'
    ));
  }

}

and change the page to:

<apex:component controller="sgf_ComponentAssignToIssue">
  <apex:attribute name="componentValue" description="Attribute on the component." type="String" required="required" assignTo="{!controllerValue}" />
    <apex:pageBlock title="My Custom Component">
      <p>
        <code>componentValue</code> is "{!componentValue}"
        <br/>
        <code>controllerValue</code> is "{!controllerValue}"
      </p>
    </apex:pageBlock>
    Notice that the controllerValue has been upper cased using an Apex method.

  <!-- just adding the following -->
  <br />
  <apex:pageMessages id="messages" />

</apex:component>

the page will error:


If I change the class to:

public with sharing class sgf_ComponentAssignToIssue {

  public String controllerValue {
    get {return controllerValue.toUpperCase();} 
    set;
  }
    
  public sgf_ComponentAssignToIssue() {
    if (String.isNotBlank(controllerValue)) {
      controllerValue.toLowerCase();
      return;
    }
    ApexPages.addMessage(new ApexPages.Message(
      ApexPages.Severity.ERROR, 
      'string is blank'
    ));
  }
}

and leave the page as is, the page will now error:


If I change it so the class looks like this:

public with sharing class sgf_ComponentAssignToIssue {

  public String controllerValue {
    get;
    set {controllerValue = value.toUpperCase();}
  }
    
  public sgf_ComponentAssignToIssue() {
    if (String.isNotBlank(controllerValue)) {
      controllerValue.toLowerCase();
      return;
    }
    ApexPages.addMessage(new ApexPages.Message(
      ApexPages.Severity.ERROR, 
      'string is blank'
    ));
  }

}

The page will work again, but still nothing works in the constructor. And if I change it to say, an Id and update the class to:

public with sharing class sgf_ComponentAssignToIssue {

  public Id controllerValue {get; set;}
  public Account passedAccount {get; set;}
    
  public sgf_ComponentAssignToIssue() {
    if (String.isNotBlank((String)controllerValue)) {
      passedAccount = new Account(Id = controllerValue);
      return;
    }
    ApexPages.addMessage(new ApexPages.Message(
      ApexPages.Severity.ERROR, 
      'Id is blank'
    ));
  }

}

and the page to pass the Id to the controller, you get:
So you can see that the controller does effect the variable but still since I can not use it in the constructor I cant really use it in the component to do anything on load... 

My Question is:
Why cant the class constructor or the getter access the variable being passed from the assignTo?