3

I'm building a VF that's meant to query for Thing__c. The fields that are meant to be filtered are set in a fieldset. I'm iterating the fieldset rendering an apex:inputField for each and have an instance of Thing__c in the controller to capture the values of each filter.

For picklists I need to be able to filter for more than one value even if they're single selection picklists so I had to write a custom component that displays two selectList and two buttons in the middle to move options from one list to another like the ones you see when selecting the fields to show in a new list view.

The custom component:

<apex:component >

    <apex:attribute name="filter" description="Filter object" type="PicklistFilter" />
    <apex:attribute name="fieldName" description="Name of the field" type="String" />

    <apex:actionRegion><apex:outputPanel layout="block">
        <div style="display: table;">
            <div style="display: table-row;">

                <div style="display: table-cell; vertical-align: top;">
                    <apex:selectList id="optionsList" size="3" value="{! filter.incoming }" style="min-width: 100px"
                        multiselect="true">
                        <apex:selectOptions value="{! filter.options }" />
                    </apex:selectList>
                </div>

                <div style="display: table-cell; vertical-align: top;">
                    <apex:commandButton value="<<" onclick="removeSelections('{! fieldName }')"
                        rerender="optionsList, selectedList" /><br />
                    <apex:commandButton value=">>" onclick="addSelections('{! fieldName }')"
                        rerender="optionsList, selectedList" />
                </div>

                <div style="display: table-cell; vertical-align: top;">
                    <apex:selectList id="selectedList" size="3" value="{! filter.outgoing }" style="min-width: 100px"
                        multiselect="true">
                        <apex:selectOptions value="{! filter.selected }" />
                    </apex:selectList>
                </div>

            </div>
        </div>
    </apex:outputPanel></apex:actionRegion>

</apex:component>

Which is inside this section of the page:

<apex:repeat value="{! $ObjectType.Thing__c.FieldSets.FiltersFieldset }"
    var="field">
    <apex:pageblocksectionitem >
        <apex:outputlabel value="{! $ObjectType.Thing__c.fields[field.fieldPath].Label }"/>
        <apex:outputPanel layout="block">
            <apex:variable var="type" value="{! $ObjectType['Thing__c'].fields[field.fieldPath].Type }"/>
            <apex:variable var="picklist" value="{! type == 'picklist' || type == 'multipicklist' }"/>
            <apex:variable var="date" value="{! type == 'date' || type == 'datetime' }" />
            <apex:outputPanel layout="none" rendered="{! NOT(picklist) }">
                <!-- regular input field -->
            </apex:outputPanel>
            <span style="{! IF(picklist,'','display: none;') }">
                <c:picklistFilter filter="{! picklistFilters[field.fieldPath] }" fieldName="{! field.fieldPath }" />
            </span>
        </apex:outputPanel>
    </apex:pageblocksectionitem>
</apex:repeat>

addSelections and addSelections are defined as actionFunction with a param outside of the iteration of the fields:

<apex:actionFunction name="addSelections" action="{! addSelections }" rerender="filters">
    <apex:param name="picklistFieldToUpdate" assignTo="{! picklistFieldToUpdate }" value="?" />
</apex:actionFunction>
<apex:actionFunction name="removeSelections" action="{! removeSelections }" rerender="filters">
    <apex:param name="picklistFieldToUpdate" assignTo="{! picklistFieldToUpdate }" value="?" />
</apex:actionFunction>

picklistFilters is a map in my controller that maps instances of this class:

public class PicklistFilter {
    private List<SelectOption> options;
    private List<SelectOption> selected;
    public List<String> incoming {get;set;}
    public List<String> outgoing {get;set;}

    public PicklistFilter(List<SelectOption> values) {
        options = new List<SelectOption>();
        options.addAll(values);
        selected = new List<SelectOption>();
        incoming = new List<String>();
        outgoing = new List<String>();
    }

    public List<SelectOption> getOptions() {
        return options;
    }

    public List<SelectOption> getSelected() {
        return selected;
    }

    public PageReference addSelections() {
        for (String s : incoming) {
            selected.add(new SelectOption(s, s));
            remove(s, options);
        }
        incoming = new List<String>();
        return null;
    }

    public PageReference removeSelections() {
        for (String s : outgoing) {
            options.add(new SelectOption(s, s));
            remove(s, selected);
        }
        outgoing = new List<String>();
        return null;
    }
}

The addSelections and removeSelections methods of the controller call the corresponding ones (named the same) in the PicklistFilter instance for a specific field

The problem with this solution is that it seems to randomly malfunction. When I move one value from the left list to the right one, generally it works. Or viceversa. But at times whatever it moves from a side to the other, it takes it back to the origin list just after it was moved.

This is how it behaves

Why is it this quirky? Feel free to ask for more code.

  • how you have defined picklistFieldToUpdate in controller? – Santanu Boral Jun 9 '17 at 21:31
  • @SantanuBoral String property. By debugging I've not found irregularities on its values. I mean, the correct picklist filter is selected to have its selections moved. – Pedro Otero Jun 9 '17 at 21:35
  • I can see String property of incoming and outgoing, not picklistFieldToUpdate – Santanu Boral Jun 9 '17 at 21:41
  • @SantanuBoral I've not pasted any of my controller code here. In third code block you'll see referenced the controller property named picklistFieldToUpdate. – Pedro Otero Jun 9 '17 at 21:43
  • Don't you this would be easy to do using Jquery plugins? a quick google search I found this plugin which I liked : crlcu.github.io/multiselect/examples/zero-configuration.html – Rao Jun 9 '17 at 23:02

Your Answer

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

Browse other questions tagged or ask your own question.