Aller au contenu
  • billets
    93
  • commentaires
    3
  • vues
    2 972

Create a Custom Salesforce Lightning Multiselect Component

Soliant Consulting

207 vues

Salesforce Lightning looks great and works beautifully. To enhance it, I’ve added a new Multiselect component. Enjoy!

Salesforce Lightning Multiselect

This is another component blog… just a small one this time, showing you how to create and use my new Multiselect component.

For some of my other components, please look here:

What I’m going to show is how to take the static HTML defined on the Salesforce Lightning Design System (SLDS) web page and turn that into an actual, working component.

Method

  • Define the event that you’ll be using first. This event is used to tell the parent component that the selected value(s) have changed
  • The event is called the “SelectChange” event.
<aura:event type="COMPONENT" description="Despatched when a select has changed value" >
  <aura:attribute name="values" type="String[]" description="Selected values" access="global" />
</aura:event>

Next, we add the markup for the actual component itself. It is composed of the button to trigger the dropdown and the dropdown itself. The button contains an icon triangle and some text indicating what has been selected. The dropdown list is an list driven by aura iteration. All selection/deselection logic is driven by the controller and helper classes.

<aura:component >

  <!-public attributes-->
  <aura:attribute name="options" type="SelectItem[]" />
  <aura:attribute name="selectedItems" type="String[]" />
  <aura:attribute name="width" type="String" default="240px;" />
  <aura:attribute name="dropdownLength" type="Integer" default="5" />
  <aura:attribute name="dropdownOver" type="Boolean" default="false" />
	
	<!-private attributes-->
  <aura:attribute name="options_" type="SelectItem[]" />
  <aura:attribute name="infoText" type="String" default="Select an option..." />
		
	<!-let the framework know that we can dispatch this event-->
  <aura:registerEvent name="selectChange" type="c:SelectChange" />

  <aura:method name="reInit" action="{!c.init}"
      description="Allows the lookup to be reinitalized">
  </aura:method>

  <div aura:id="main-div"  class=" slds-picklist slds-dropdown-trigger slds-dropdown-trigger--click ">
	
	  <!-the disclosure triangle button-->
    <button class="slds-button slds-button--neutral slds-picklist__label" style="{!'width:' + v.width }" 
      aria-haspopup="true" onclick="{!c.handleClick}" onmouseleave="{!c.handleMouseOutButton}">
      <span class="slds-truncate" title="{!v.infoText}">{!v.infoText}</span>
      <lightning:icon iconName="utility:down" size="small" class="slds-icon" />
    </button>

	<!-the multiselect list-->
    <div class="slds-dropdown slds-dropdown--left" onmouseenter="{!c.handleMouseEnter}" onmouseleave="{!c.handleMouseLeave}">
      <ul class="{!'slds-dropdown__list slds-dropdown--length-' + v.dropdownLength}" role="menu">

        <aura:iteration items="{!v.options_}" var="option">
          <li class="{!'slds-dropdown__item ' + (option.selected ? 'slds-is-selected' : '')}" 
            role="presentation" onclick="{!c.handleSelection}" data-value="{!option.value}" data-selected="{!option.selected}">
            <a href="javascript:void(0);" role="menuitemcheckbox" aria-checked="true" tabindex="0" >
              <span class="slds-truncate">
            <lightning:icon iconName="utility:check" size="x-small" class="slds-icon slds-icon--selected slds-icon--x-small slds-icon-text-default slds-m-right--x-small" />{!option.value}
          </span>
            </a>
          </li>
        </aura:iteration>

      </ul>
    </div>
  </div>
</aura:component>

As you can see, this is mostly just basic HTML and CSS using the Salesforce Lightning Design System.
To make it work, we implement a Javascript controller and handler.

These Javascript objects load and sort “items” into the select list:

   init: function(component, event, helper) {

      //note, we get options and set options_
      //options_ is the private version and we use this from now on.
      //this is to allow us to sort the options array before rendering
      var options = component.get("v.options");
      options.sort(function compare(a,b) {
                     if (a.value == 'All'){
                       return -1;
                     }
                     else if (a.value &lt; b.value){
                       return -1;
                     }
                     if (a.value &gt; b.value){
                       return 1;
                     }
                     return 0;
                   });

      component.set("v.options_",options);
      var values = helper.getSelectedValues(component);
      helper.setInfoText(component,values);
    },

As you can see, I’m not touching any HTML – I’m relying on Lightning’s binding framework to do the
Actual rendering – by adding to the options list, Lightning will apply that to the “
object defined in the component and render the list (hidden initially).
Also note that there is an ‘All’ value that the system expects. Change this to whatever you like, or
even remove it, but remember to change the text here in the controller :).

Another interesting area to explain is how selecting/deselecting is done:

    handleSelection: function(component, event, helper) {
      var item = event.currentTarget;
      if (item &amp;&amp; item.dataset) {
        var value = item.dataset.value;
        var selected = item.dataset.selected;

        var options = component.get("v.options_");

        //shift key ADDS to the list (unless clicking on a previously selected item)
        //also, shift key does not close the dropdown (uses mouse out to do that)
        if (event.shiftKey) {
          options.forEach(function(element) {
            if (element.value == value) {
              element.selected = selected == "true" ? false : true;
            }
          });
        } else {
          options.forEach(function(element) {
            if (element.value == value) {
              element.selected = selected == "true" ? false : true;
            } else {
              element.selected = false;
            }
          });
          var mainDiv = component.find('main-div');
          $A.util.removeClass(mainDiv, 'slds-is-open');
        }
        component.set("v.options_", options);
        var values = helper.getSelectedValues(component);
        var labels = helper.getSelectedLabels(component);
        
        helper.setInfoText(component,values);
        helper.despatchSelectChangeEvent(component,labels);

      }
    },

I am using a custom object: ‘SelectItem’ because I’m not able to create a ‘selected’ attribute on
Salesforce’s built in version. In the code above, I’m looking at this value and either adding
the item to the list, replacing the list with this one item or removing it. In this case I’m using
the shift key, but this can be customized to any key. Finally, I update the text with the new value
and if multiple value, the count of values.

One tricky area was handling hiding and showing of the select list – I use the technique below:


    handleClick: function(component, event, helper) {
      var mainDiv = component.find('main-div');
      $A.util.addClass(mainDiv, 'slds-is-open');
    },

    handleMouseLeave: function(component, event, helper) {
      component.set("v.dropdownOver",false);
      var mainDiv = component.find('main-div');
      $A.util.removeClass(mainDiv, 'slds-is-open');
    },
    
    handleMouseEnter: function(component, event, helper) {
      component.set("v.dropdownOver",true);
    },

    handleMouseOutButton: function(component, event, helper) {
      window.setTimeout(
        $A.getCallback(function() {
          if (component.isValid()) {
            //if dropdown over, user has hovered over the dropdown, so don't close.
            if (component.get("v.dropdownOver")) {
              return;
            }
            var mainDiv = component.find('main-div');
            $A.util.removeClass(mainDiv, 'slds-is-open');
          }
        }), 200
      );
    }
  }
  • When the button is clicked, the list is shown.
  • When the mouse leaves the button, but does not enter the dropdown – it closes
  • When the mouse leaves the button, and enters the dropdown, the close is cancelled.
  • When the mouse leaves the list, it hides.

Seems simple, but getting it working nicely can be tough.

To use, simply add as part of a form (or without if you’d like):

<div class="slds-form-element">
    <label class="slds-form-element__label" for="my-multi-select">Multi Select!!</label>
    <div class="slds-form-element__control">
        <c:MultiSelect aura:id="my-multi-select" options="{!v.myOptions}" selectChange="{!c.handleSelectChangeEvent}" selectedItems="{!v.mySelectedItems}" />
    </div>
</div>

Here’s what it looks like:

MultiSelect

The MultiSelect item in action

That’s all for now.

Enjoy!

The post Create a Custom Salesforce Lightning Multiselect Component appeared first on Soliant Consulting.


Afficher la totalité du billet



0 Commentaire


Commentaires recommandés

Il n’y a aucun commentaire à afficher.

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant

×