2 minute read

I recently had the problem that I wanted to pass a variable from a Visualforce page to a Visualforce component and assign it to the component’s controller.

So far so good, no problems at all, but then I wanted the controller’s variable to be updated when the variable on the page is changed during a re-render.

The page looks like this

<apex:page controller="PageController">

    <apex:includeScript value="{!URLFOR($Resource.res,'lib/jquery/js/jquery-1.4.2.min.js')}" />
    <script type="text/javascript">
        var jq$ = jQuery.noConflict();

    <apex:form >
    <!-- Page block with the display options and refresh button -->
    <apex:pageBlock >
        <apex:pageBlockButtons location="top">
            <apex:selectList id="cbMode" value="{!selectedMode}" size="1">
                <apex:selectOptions value="{!Modes}"/>
            <apex:selectList id="cbDay" value="{!selectedDay}" size="1">
                <apex:selectOptions value="{!Days}"/>
            <apex:commandButton value="Refresh" action="{!onRefresh}" rerender="mySection,pgMap" 
                oncomplete="jQuery(document).trigger('updateData');" status="status"/>
            <apex:actionstatus id="status" startText="reading...">

           <apex:panelGroup id="pgMap"> 
                <c:Map data="{!tourlist}" mode="{!selectedMode}"/>

and the component like this

<apex:component controller="SCMapController" selfClosing="true" rendered="true">

    <apex:attribute description="The actual data to show on the map"

<apex:inputHidden value="{!data}" id="tourData" />

var tourData = {!mapDataConverted};

I wanted to use an assignTo to assign the attribute to a variable in the controller, convert the content to a JS object string and then read the variable in a JS script part. This works perfectly fine for the first call of the page, but after pressing the Refresh button, that re-renders the component I still have the old data on the JS side.

Some debugging revealed that the changed data isn’t passed to the controller sigh

I finally used a different approach: I assign the variable to a hidden field, which serializes the variable to something like this:

                 infoAddress= Brakenstraat 36A 5555 CL Valkenswaard
                 infoAddress=Some data

The basic idea is to use this string and convert it to something that can be used in JavaScript. My object is in fact a list of map data objects that contains some fields and a list of items.

 * Convert the serialized version (string) of an sObject to an
 * JS object. You get the serialized sObject by assigning a data
 * structure to an hidden field for example
 * @param data String of the serialized sObject
 * @return JS Object of the data
function sObject2JSObject(data)
 data = data.replace(/^\[/,'');
 data = data.replace(/\]$/,'');
 data = data.replace(/\w+:\[/g, '[')
 data = data.replace(/\[/g,'{');
 data = data.replace(/\]/g, '}');
 data = data.replace(/=\(/g, ':[');
 data = data.replace(/\)/g, ']');
 data = data.replace(/=([^,}]*)([,}])/g, "='$1'$2");
 data = data.replace(/=/g, ':');
 data = "[" + data + "]";

 var tmpData;
 eval("tmpData=" + data);

 return tmpData;

The JS function sObject2JSObject() accepts the serialized string and returns the JS object created from it. The function is far from complete, but may help other as a starting point…