function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
RustyboyRustyboy 

Field value not being set in VisualForce component

Hi,

I have a VisualForce component that presents a SelectList of TimeZones using a jQuery dialog. I have used an "onChange" event on the SelectList with action support that attempts to return the selected value using action support.

All seems to work ok, but the selected time zone does not appear to be set; at least it comes through as a null on the setter. 

I have tried all kinds of things but cannot get this to work properly - - I have used this technique successfully elsewhere, though not in a component.

Here are the relevant code excerpts:

The component
 
<apex:component controller="TimeZonePickerController">

    <apex:includeScript value="{!URLFOR($Resource.jQuery, 'jquery-ui-1.12.1.custom/external/jquery/jquery.js')}"/>
    <apex:includeScript value="{!URLFOR($Resource.jQuery, 'jquery-ui-1.12.1.custom/jquery-ui.js')}"/>
    <apex:stylesheet value="{!URLFOR($Resource.jQuery, 'jquery-ui-1.12.1.custom/jquery-ui.css')}"/>
    

	<script>
    	// Create a new alias for jQuery (j$)
		var j$ = jQuery.noConflict();
	    
	    // When document loaded show the dialog
        j$(document).ready(function(){        
            j$("#dialog").dialog(
            {
                title:"Select a Time Zone",
                autoOpen: false,							
                width:510,
                height:70,
                modal:true,
                closeable:false,
                resizable:false,
                draggable:true
            });
            
            j$("#dialog").dialog('open');					
        }); 


        function closeTheDialog() {
            j$('#dialog').dialog('close');
        }


        function tzChanged(chosenTz) {    

	        // Perform the action - call to Apex
            doAction();
                                    
            // Close the dialog
            closeTheDialog();

        }            

	</script>

	<apex:attribute name="attrTimePickerData"
	    				assignTo="{!theData}"
	    				description=""
	                    type="TimePickerData"/>

                    
	<div id="dialog"> 
		<apex:outputPanel >	
			 
			<apex:selectList id="TimeZone" value="{!selectedTimeZoneStr}" size="1" onchange="tzChanged(this);">
				<apex:selectOptions value="{!TimeZones}"/>
			</apex:selectList>
 			
			<apex:actionFunction name="doAction" action="{!selectTz}"/>
								
		</apex:outputPanel>
	</div>
			
</apex:component>

The component controller:
public with sharing class TimeZonePickerController {

	public TimePickerData theData;
	public List<SelectOption> TimeZones {get; set;} 
	public String selectedTimeZoneStr; 
	private boolean timeZonesFetched = false;			

	public TimeZonePickerController() {
	}

	public TimePickerData getTheData() {
		return theData;		
	}

	public void setTheData(TimePickerData argTheData) {
		theData = argTheData;
		
		// Establish time picker settings for the given type 
		// (Using setter because it is the first time the class TimePickerData is populated)
		buildTimeZoneList();
		
		// Default timezone to user's if not already set
		if (string.isNotBlank(theData.selectedTimeZoneStr)) {
			selectedTimeZoneStr = theData.selectedTimeZoneStr;							
		} else {
			selectedTimeZoneStr = UserInfo.getTimeZone().getID();
		}			
	}	
	
	public String getSelectedTimeZoneStr() {
		return selectedTimeZoneStr;
	}

	public void setSelectedTimeZoneStr(String argSelectedTimeZoneStr) {
	
system.debug('---------- TZ PICKER COMPONENT - setSelectedTimeZoneStr: Start - Value: ' + argSelectedTimeZoneStr);
	
		selectedTimeZoneStr = argSelectedTimeZoneStr;
	
system.debug('---------- TZ PICKER COMPONENT - setSelectedTimeZoneStr - Value: ' + argSelectedTimeZoneStr);
			
		// Set the TimeZone as string and Timezone for return to calling page
		theData.selectedTimeZoneStr = selectedTimeZoneStr;									
//		theData.selectedTimeZone = TimeZone.getTimeZone(theData.selectedTimeZoneStr);									

system.debug('---------- TZ PICKER COMPONENT - setSelectedTimeZoneStr: End');
	}	

    public PageReference selectTz()
    {
		// Close the dialog - does this work?
		theData.displayTzPicker = false;

system.debug('---------- TZ PICKER COMPONENT - selectTz - Str value: ' + selectedTimeZoneStr);
system.debug('---------- TZ PICKER COMPONENT - selectTz - The Data value: ' + theData.selectedTimeZoneStr);
    
        return null;
    
    }

    public void buildTimeZoneList() {
    	
    	// Already fetched?
    	if (timeZonesFetched) {
    		return;
    	}

		// Build timezones
		TimeZones = new List<SelectOption>();
		Schema.DescribeFieldResult fieldResult = User.TimeZoneSidKey.getDescribe();			// Descibes the field in an object  (User in this case)
		List<Schema.PicklistEntry> PkListEntry = fieldResult.getPicklistValues();			// Returns the picklist options
		for( Schema.PicklistEntry  pkEnt : PkListEntry) {
			TimeZones.add(new SelectOption(pkEnt.getValue(), pkEnt.getLabel()));
		}       

		timeZonesFetched = true;


    }
	
}

NB: The component was working perfectly until I turned into a jQuery modal dialog!


 
Zuinglio Lopes Ribeiro JúniorZuinglio Lopes Ribeiro Júnior

Hello Rusty,

To set the value in the controller, try adding a apex:param to apex:actionfunction and then you can pass the selected value as a parameter of your doAction function.

To read more about:

https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_compref_actionFunction.htm
https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_compref_param.htm

Furthermore, an action function must be a child of an apex:form. So with a few changes your VF should look like this:
 

<apex:component controller="TimeZonePickerController">

    <apex:includeScript value="{!URLFOR($Resource.jQuery, 'jquery-ui-1.12.1.custom/external/jquery/jquery.js')}"/>
    <apex:includeScript value="{!URLFOR($Resource.jQuery, 'jquery-ui-1.12.1.custom/jquery-ui.js')}"/>
    <apex:stylesheet value="{!URLFOR($Resource.jQuery, 'jquery-ui-1.12.1.custom/jquery-ui.css')}"/>
    

	<script>
    	// Create a new alias for jQuery (j$)
		var j$ = jQuery.noConflict();
	    
	    // When document loaded show the dialog
        j$(document).ready(function(){        
            j$("#dialog").dialog(
            {
                title:"Select a Time Zone",
                autoOpen: false,							
                width:510,
                height:70,
                modal:true,
                closeable:false,
                resizable:false,
                draggable:true
            });
            
            j$("#dialog").dialog('open');					
        }); 


        function closeTheDialog() {
            j$('#dialog').dialog('close');
        }


        function tzChanged(el) {    

	        // Perform the action - call to Apex
            doAction(el.value);
                                    
            // Close the dialog
            closeTheDialog();

        }            

	</script>

	<apex:attribute name="attrTimePickerData"
	    				assignTo="{!theData}"
	    				description=""
	                    type="TimePickerData"/>

                    
	<div id="dialog"> 
		<apex:outputPanel >	
			 
			<apex:selectList id="TimeZone" value="{!selectedTimeZoneStr}" size="1" onchange="tzChanged(this)">
				<apex:selectOptions value="{!TimeZones}"/>
			</apex:selectList>		
			<apex:form>
				<apex:actionFunction name="doAction" action="{!selectTz}">
					 <apex:param name="firstParam" assignTo="{!selectedTimeZoneStr}" value="" />
				</apex:actionFunction>
			</apex:form>
	
		</apex:outputPanel>
	</div>
			
</apex:component>
Hope to have helped!

Regards.

Don't forget to mark your thread as 'SOLVED' with the answer that best helps you.
 
RustyboyRustyboy
Thanks for this.

I added the param and the call within the js, but still not setting. I have similar code working in a page that is not within a component; feels like this may be an issue with using a component.

ps: The component itself is within a form so cannot add another form. However, the action function is firing, I can even see the selected value in a js alert, but it is not getting set in the controller.

Here are the relevant code excerpts for completeness (ps renamed "doAction" to "chooseTz" to make the code more specific:
 
function tzChanged(chosenTz) {    
        
        alert(chosenTz.value);
        	              
	    // Perform the action - call to Apex
        chooseTz(chosenTz.value);
                                    
        // Close the dialog
        closeTheDialog();
}


<div id="dialog">
    <apex:outputPanel > 
        <apex:selectList id="TimeZone" value="{!selectedTimeZoneStr}" size="1" title=""
 	          onchange="tzChanged(this);" >
 	        <apex:selectOptions value="{!TimeZones}"/>
        </apex:selectList>
			
        <apex:actionFunction name="chooseTz" action="{!selectTz}">
	        <apex:param name="chosenTz" assignTo="{!testThisThing}" value="" />
        </apex:actionFunction>
    </apex:outputPanel>
</div>

Thanks
Alex KolyadichAlex Kolyadich
<div id="dialog">
    <apex:form>
        <apex:outputPanel >  
            <apex:selectList id="TimeZone" value="{!selectedTimeZoneStr}" size="1" onchange="tzChanged(this);">
                <apex:selectOptions value="{!TimeZones}"/>
            </apex:selectList>
            <apex:actionFunction name="doAction" action="{!selectTz}"/>
        </apex:outputPanel>
    </apex:form>
</div>
Add apex:form tag in yor div that you use as "dialog".