jQuery select2 with WordPress

Solution:

Click Twice

The first click on the cell initialises select2, the second click then tells select2 to display the dropdown. To only require a single click you can call the open method described at https://select2.org/programmatic-control/methods after select2 is initialized.

// Initialise select2
let selectEle = cellEle.children("select").select2();
// Open the select2 dropdown
selectEle.select2('open');

Replace Select

When clicking on a value select2 is being destroyed, the .html() call should replace the select with the selected value, however it does not function correctly as the id property doesn’t exist on the stored value, this is causing the cell to revert to a normal select.

The code which handles the "select2:close" event contains the line selectedValue = selectEle.select2('data')[0]['text']; which places the text of a just the first selected value [0] into the variable selectedValue. After this the HTML of the cell is updated using cellEle.html(selectedValue.id);, but at this point selectedValue contains just the text (e.g. “Alabama”) so there is no .id property. To resolve this both the ID and Text could be stored in the array, then used where needed, for example:

// Store the id and text of all selected values in the array
selectedValue = selectEle.select2('data').map(function(value) {
  return { id: value.id, text: value.text }; 
});

// Get an array of IDs for the selected values (for preselecting values when select2 loads)
selectEle.val(states[cellId].map(function(value) { return value.id })).trigger('change');

// Get a comma separated string of the selected values (for populating the text in the cell)
cellEle.html(states[cellId].map(function(value) { return value.text; }).join(','));

Multi Select Mode – An example which allows multiple selections is https://jsfiddle.net/aqgbxz1d/ and also incorporated into this answer below. This seems to be the desired mode based on the multiple="multiple" property in the question.

The example is updated to no longer use the select2:close event. Instead it uses the change event to store value changes, and a second click event handler on the document to destroy the select2 dropdown(s) when the user clicks somewhere else on the page. This seems like a better approach given what you are trying to achieve as it leaves the select open for multiple values to be selected.

Single Select Mode – From the comments it seems single select mode may be required. An example which allows just a single selection is https://jsfiddle.net/9jcnwbt2/1/. If single select mode is required, then you would need to:

  • Remove the multiple attribute multiple="multiple"
  • add a blank option <option></option>
  • You could also replicate replicate the code from the document click event which destroys select2 and updates the HTML into the change event.

 

(function ($) {
  var states = [];

  $(document).ready(function () {
    $(".volunteer").on("click", function (e) {
      // Check if select is already loaded
      if (!$(this).has("select").length) {
        var cellEle = $(this);
        var cellId = this.id;

        // Populate select element
        cellEle.html(`<select class="js-example-basic" multiple="multiple">
                    <option value="AL">Alabama</option>
                    <option value="WY">Wyoming</option>
                    </select>`);

        // Initialise select2
        let selectEle = cellEle.children("select").select2({placeholder: "Select a value"});

        // Open the select dropdown so user doesn't have to click twice
        selectEle.select2('open');

        // Check if there is an existing value for this cell
        if (states[cellId]) {
          // preselect existing value
          selectEle.val(states[cellId].map(function (value) {
            return value.id
          })).trigger('change');
        }

        // Attach event handler to store value changes
        selectEle.on('change', function (e) {

          // Get selected values
          selectedValues = $(this).select2('data');

          // Update the states array with id and text of selected 
          // values. The id is needed to restore the values if select2
          // is reloaded on this cell. The text is required to generate
          // the replacement text shown in the cell
          states[cellId] = selectedValues.map(function (value) {
            return {
              id: value.id,
              text: value.text
            };
          });
        });
      }

      // Don't propagate the event
      // This prevents this document click handler from executing which would
      // remove select2 by calling destroy
      e.stopPropagation();
    });
  });

  // Attach event handler to document to capture any clicks
  // This will be triggered for all clicks on the page, except those 
  // captured by the method described above this prevents this firing
  // with e.stopPropagation()
  // Which this is called select2 on any cells must be destoryed and their 
  // text value populated
  $(document).on('click', function (e) {
    // Loop through all select2 elements
    $('.js-example-basic').each(function (idx) {
      // Get the ID of the cell that's been selected
      let cellId = $(this).parent().attr('id');

      // Destroy select2 on this element
      $(this).select2('destroy');

      // Change html on the parent element (td) to just show the value
      if(states[cellId] && states[cellId].length > 0){
        $(this).parent().html(states[cellId].map(function (value) {
          return value.text;
        }).join(','));
      } else {
        $(this).parent().html("Select a value...")
      }
    });
  });

})(jQuery)
.js-example-basic {
  width: 200px;  
}

thead{
    font-weight: bold;
}

table, th, td {
  border: 1px solid black;
}

tr {
  height: 36px;
}

td {
  width: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />

<table>
  <thead>
    <tr>
      <td>Table Header 1</td>
      <td>Table Header 2</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="volunteer" id="47">Select a value...</td>
      <td class=""></td>
    </tr>
    <tr>
      <td class="volunteer" id="48">Select a value...</td>
      <td class=""></td>
    </tr>
  </tbody>
</table>

Solution:2

You can try this also

if (name.toUpperCase() !='' && coundivy.toUpperCase() != 'ALL' && age.toUpperCase() != 'ALL') {
  if (rowCoundivy.toUpperCase() == coundivy.toUpperCase() && rowAge == age && rowName.toLowerCase().includes(name.toLowerCase())) {
     $(this).show();
  } else {
   $(this).hide();
  } }

Solution:2

You can try this also

if (name.toUpperCase() !='' && coundivy.toUpperCase() != 'ALL' && age.toUpperCase() != 'ALL') {
  if (rowCoundivy.toUpperCase() == coundivy.toUpperCase() && rowAge == age && rowName.toLowerCase().includes(name.toLowerCase())) {
     $(this).show();
  } else {
   $(this).hide();
  } }