1

Say I am having the below code:

        <apex:selectCheckboxes value="{!SelectedLists}" styleClass="convertToLSD" layout="pageDirection">
            <apex:selectOptions value="{!list_options}"/>
        </apex:selectCheckboxes>

And want to convert that into slds look and feel, how should I achieve it?

I have an approach coming from this blog: https://vishnuvaishnav.wordpress.com/2015/09/17/convert-visualforce-checkboxes-in-lightning-design-system-using-javascript/ .

I wouldn't say it is a bad approach except the mixture of using jQuery and vanilla JS is a bit interesting. However, it is still hacking into the VF page. Is there a no-hacking way of achieving this?

1 Answer 1

4

Follow the same practices for the checkbox here:

SLDS and inputField checkbox

And use a repeat to populate the options

<fieldset class="slds-form-element">
    <legend class="slds-form-element__legend slds-form-element__label">Checkbox Group Label</legend>
    <div class="slds-form-element__control" id="chk_options">
        <apex:repeat value="{!YOUROPTIONS}" var="opt">
            <span class="slds-checkbox">
                <label class="slds-checkbox">
                    <apex:inputcheckbox styleclass="slds-input"/>
                    <span class="slds-checkbox--faux"></span>
                    <span class="slds-form-element__label">{!opt}</span>
                </label>
            </span>
        </apex:repeat>
    </div>
</fieldset>

<apex:inputHidden value="{!checkedOption}" id="checked_option"/>

Then you can use JS to set the value of the hidden input or a myriad of different ways to get the selected value to the controller.

In this case you need to use a bit of JS.....

You could even go so far as to create a wrapper class to store the label and the isSelected Boolean and forgo the selectOptions. Then you could bind each input to the wrapper instance and iterate over them to get the selected value in the controller. This would negate the need for JS on the page to set the value in the controller

Note The above is meant to convey the idea not necessarily a compete working example.

It is much easier to develop a DOM using SLDS that utilizes existing features (repeat, bindings, controller, action functions, JS, etc) than to use existing VF components and try to modify the DOM to make them look like SLDS after the fact.

There are several cases like this where currently existing VF components do not have a direct SLDS equivalent so you will have to combine regular HTML and some JS. Throw in a repeat to create DOM elements as needed

When trying to style VF pages for SLDS you need to change your thinking a bit and use the best of both worlds (VF and SLDS). JS should almost never (currently) need to be used to modify the DOM after the fact to make something look like SLDS. If that is where you find yourself going, take a step back and look at it a bit differently.

Example

Controller

public with sharing class testController {

    public string selectedOption {
        get{
            for(chkOptions opt : chkOptions){
                if(opt.isSelected == true) return opt.label;
            }

            return null;
        }

    }

    public chkOptions[] chkOptions {get;set;}

    public testController(){
        chkOptions = New chkOptions[]{};

        for(integer x=0; x<5; x++)
            chkOptions.add( New chkOptions('Option: ' + x));
    }

    public class chkOptions{

        public string label {get;set;}
        public boolean isSelected {get;set;}

        public chkOptions(string label){
            this.label = label;
        }

    }


}

VF Page

<apex:page id="testPage" controller="testController">

    <head>

        <apex:insert name="title"/>

        <apex:stylesheet value="{!URLFOR($Resource.SLDS, 'assets/styles/salesforce-lightning-design-system-vf.min.css')}" />

    </head>



    <div class="SDLS">

        <body>

        <apex:form >
            <apex:actionFunction name="render_result" rerender="results"/>
        <fieldset class="slds-form-element">
            <legend class="slds-form-element__legend slds-form-element__label">Checkbox Group Label</legend>
            <div class="slds-form-element__control" id="chk_options">
                <apex:repeat value="{!chkOptions}" var="opt">
            <span class="slds-checkbox">
                <label class="slds-checkbox">
                    <apex:inputcheckbox value="{!opt.isSelected}" onchange="render_result();" styleclass="slds-input"/>
                    <span class="slds-checkbox--faux"></span>
                    <span class="slds-form-element__label">{!opt.label}</span>
                </label>
            </span>
                </apex:repeat>
            </div>
        </fieldset>
        </apex:form>

        <apex:outPutPanel layout="block" id="results">
            {!selectedOption}
        </apex:outPutPanel>

        </body>

    </div>


</apex:page>

On load

enter image description here

After Select

enter image description here

The above does not enforce only one option to be selected. If that is the case you can use some JS to control that

Using Option one with no controller update

Controller

public with sharing class testController {

    public string selectedOption {get;set;}

    public selectOption[] chkOptions {
        get{
            if(chkOptions == null){
                chkOptions = New SelectOption[]{
                        New SelectOption('A','Option 1'),
                        New SelectOption('A','Option 2'),
                        New SelectOption('A','Option 3'),
                        New SelectOption('A','Option 4')

                };
            }

            return chkOptions;
        }
        set;
    }


}

VF Page

<apex:page id="testPage" controller="testController">

    <head>
        <apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"/>

        <apex:insert name="title"/>

        <apex:stylesheet
                value="{!URLFOR($Resource.SLDS, 'assets/styles/salesforce-lightning-design-system-vf.min.css')}"/>


    </head>


    <div class="slds">

        <body>

        <apex:form>
            <apex:actionFunction name="render_result" rerender="results"/>

            <!--<apex:selectCheckboxes value="{!selectedOption}">-->
                <!--<apex:selectOptions value="{!chkOptions}"/>-->
            <!--</apex:selectCheckboxes>-->
            <apex:inputHidden value="{!selectedOption}" id="sel_opt"/>

            <fieldset class="slds-form-element">
                <legend class="slds-form-element__legend slds-form-element__label">Checkbox Group Label</legend>
                <div class="slds-form-element__control" id="chk_options">
                    <apex:repeat value="{!chkOptions}" var="opt">
                            <span class="slds-checkbox">
                                <label class="slds-checkbox">
                                    <input type="checkbox" data-value="{!opt.value}" styleclass="slds-input"/>
                                    <span class="slds-checkbox--faux"></span>
                                    <span class="slds-form-element__label">{!opt.label}</span>
                                </label>
                            </span>
                    </apex:repeat>
                </div>
            </fieldset>


        </apex:form>

        <apex:outPutPanel layout="block" id="results">
                {!selectedOption}
        </apex:outPutPanel>

        </body>

    </div>

    <script>
        $('[id$=chk_options] input').on('change', function () {
            if ($(this).is(':checked')) {
                $('[id$=sel_opt]').val($(this).attr('data-value'));
            }
            render_result();
        });
    </script>


</apex:page>
9
  • Thank you, Eric. In this case, I would prefer a bit hacking into this solution for now.
    – Lance Shi
    Commented Nov 25, 2016 at 3:17
  • @LanceShi - Not sure I agree but to each their own. See updated answer with working example. Maybe it will change your mind?
    – Eric
    Commented Nov 25, 2016 at 3:20
  • When I look at your code, I am always 100 percent sure it will work. There is no question about it. However, some work will definitely be involved - creating a wrapper class, update the initialization and the front-end javascript code. It is just my personal preference though which thinks hacking into VF page is not that bad.
    – Lance Shi
    Commented Nov 25, 2016 at 3:31
  • For me, it is always like the compromise between extra effort and the risk of using hacking into VF methodology. Everyone might has its own judgement as this point. I will accept your answer because I think it is the best if we insist on not hacking into VF page.
    – Lance Shi
    Commented Nov 25, 2016 at 3:32
  • 1
    So many ways to do things. Each of which is right for someone under so many different circumstances...
    – Eric
    Commented Nov 25, 2016 at 3:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .