1

My visualforce component has the following attribute:

<apex:attribute type="SObject[][]" name="var" 
    description="Variable to store results in." 
    assignTo="{!searchResults}" required="true"/>

My components controller has the following variable:

public List<List<SObject>> searchResults {get; set;}

My page's controller has the following variable:

public List<List<SObject>> searchResults {get; set;}

My page references my component as such:

<c:EmailRecipientSearch var="{!searchResults}"/>

I am getting the following error when deploying:

force-app\main\default\pages\SendEmailForm.page Wrong type for attribute . Expected SObject[][], found VisualforceArrayList

The question:

How do I pass a List<List<SObject>> to a component via an attribute.

I know I could create a wrapper class and pass that instead but I'd like to avoid that.

The use case:

I need to pass data from my component back to my page. This was something I've done in the past but have forgotten how to make it work. I read through this question. I vaguely remembered being able to make it work without passing the entire controller and I wanted to test if my memory was correct.

I understand I can test this without needing to past a List<List<SObject>> but I do have a few other use cases where I would need to pass a nested list as an attribute so I figured I'd ask if anyone knew.

3

Sad to say, the VF Custom Components documentation is explicit

One-dimensional lists, specified using array-notation, such as String[], or Contact[].

You'll need to pass a custom type instead.

0

Visual force is pretty good at auto-casting values to the correct object type. For most usages you can probably just declare the parameter as type Object[]. For your particular example I might use:

<apex:attribute type="Object[]" name="var" 
    description="Variable to store results in." 
    assignTo="{!searchResultsAttr}" required="true"/>

Where you controller instead uses:

public List<Object> searchResultsAttr { get; set;}

public List<List<SObject>> searchResults {
    get { return (List<List<SObject>>)searchResultsAttr; }
    set { searchResultAttr = (List<Object>)value; }
}

Just so my controller will also have easy access to the casted value.

But more often that not, I find my usage doesn't requiring casting inside the controller. For example:

<apex:attribute name="query" description="Query to use" type="String" required="true" assignTo="{!queryString}" />
<apex:attribute name="params" description="An array of parameters to use in the query" type="Object[]" required="false" assignTo="{!queryParams}" />

with:

public String queryString { get; set; }

public List<Object> queryParams { get; set; }

Object getQueryParam(Integer i) {
    Object retval = null;
    if(queryParams != null && queryParams.size() > i) {
        retval = queryParams[i];
    }
    return retval;
}

public ApexPages.StandardSetController getStandardSetController() {
    ApexPages.StandardSetController retval = null;
    if(queryString != null) {
        final Object param0 = getQueryParam(0);
        final Object param1 = getQueryParam(1);
        final Object param2 = getQueryParam(2);
        final Object param3 = getQueryParam(3);
        final Object param4 = getQueryParam(4);
        final Object param5 = getQueryParam(5);
        final Object param6 = getQueryParam(6);
        final Object param7 = getQueryParam(7);
        final Object param8 = getQueryParam(8);
        final Object param9 = getQueryParam(9);
        retval = new ApexPages.StandardSetController(
            Database.getQueryLocator(queryString) );
    }
    return retval;
}

Have fun.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.