+1 vote
by (163k points)

I have an interesting situation where I'* testing a VF Component by passing string literals from a VF Page. Some of these strings are then fed to a Custom Component Controller to be modified before being output. The strange thing is that the strings can't be modified by the custom component controller.

Here's the code:

VF Page (for testing the VF component)


    <c:Calendar description="A description \n with a new line \n again" xAltDesc="Something with \n and another \n new line break" dtstart="something" dtend="something" summary="A new summary" location="A location" />


VF Component

<apex:component controller="FormatController">BEGIN:VCALENDAR 
DESCRIPTION:<apex:outputText escape="false" value="{!descriptionFormat}" /> 
X-ALT-DESC;FMTTYPE=text/html:<apex:outputText escape="false" value="{!xAltDescFormat}" /> 
DTSTAMP:<apex:outputText value="{0,date,yyyyMMdd'T'HHmmssZ}"><apex:param value="{! NOW() }" /></apex:outputText> 
DTSTART:<apex:outputText value="{!dtstart}" />
DTEND:<apex:outputText value="{!dtend}" />
SUMMARY:<apex:outputText value="{!summary}" />
UID:<apex:outputText value="{0,date,yyyyMMddHHmmssSSS}@test.com"><apex:param value="{! NOW() }" /></apex:outputText> 
LOCATION:<apex:outputText value="{!location}" /> 
    <apex:attribute name="description" type="String" description="DESCRIPTION" assignTo="{!descriptionFormat}" />
    <apex:attribute name="xAltDesc" type="String" description="X-ALT-DESC" assignTo="{!xAltDescFormat}"/>
    <apex:attribute name="dtstart" type="String" description="DTSTART" />
    <apex:attribute name="dtend" type="String" description="DTEND" />
    <apex:attribute name="summary" type="String" description="SUMMARY" />
    <apex:attribute name="location" type="String" description="LOCATION" />

VF Component's Custom Controller

public with sharing class FormatController {
    public String descriptionFormat {
        get { return removeNewLines(descriptionFormat); }
        set { descriptionFormat = value; }

    public String xAltDescFormat {
        get { return removeNewLines(xAltDescFormat); }
        set { xAltDescFormat = value; }
    public FormatController() {}
    public String removeNewLines(String inputString) {
        return inputString.replaceAll('\n', '');

The expected outcome is that both descriptionFormat and xAltDescFormat will have the \n characters removed. This code works as expected in execute anonymous Apex but not as shown above (the original strings from the VF Page are output).

Now the strange part is that when I add a custom controller for the VF Page and pass the strings as controller variables, everything works fine!

More code:

VF Page Custom Controller

public class CalendarPageController {

    public String testDescription = 'A description \n with a new line \n again';
    public CalendarPageController() {
    public String getTestDescription() { return testDescription; }

Modified VF Page

<apex:page controller="CalendarPageController">

    <c:Calendar description="{!testDescription}" xAltDesc="Something with \n and another \n like that" dtstart="something" dtend="something" summary="A new summary" location="A location" />


Now testDescription works as expected, but because xAltDesc is a String literal, it still can't be modified.

All of this to say: is this expected behavior?

1 Answer

+1 vote
by (163k points)
Best answer

This is expected behavior, though not clearly documented anywhere I can tell, as a literal cannot be modified, and so acts as a one-way data binding. If you need a "working copy", you'd want to write a setter method:

String descriptionFormatInternal, descriptionFormatOld;
public void setdescriptionFormat(String value) {
  if(value != descriptionFormatOld) {
    descriptionFormatInternal = descriptionFormatOld = value;

Or, as you observed, setting up a variable in the parent page's controller will have the same benefit.

Welcome to Memory Exceeded, where you can ask questions and receive answers from other members of the community.