Update contents of select2 control and reselect previous selections

I’ve created a site for sharing some old family letters. I’m using two Select2 controls to let people filter who wrote the letters and who received them. It’s all working nicely, but I’d like to have each select2 get filtered based on what was selected in the other one. That is, if a user chooses a particular letter writer, then I’d like the select2 of recipients to show only people that letter writer wrote to. I’ve actually got that part working, but updating the contents of the dropdown removes any selections it had, and I can’t get updating the selections to work.

A few notes and then I’ll show some code and try to clarify what I’m seeing and trying.

  1. Both select2 controls are set up for multiple selection.
  2. There’s a MySQL database that contains the information about what letters exist, who they were written by, and who they were sent to.

The HTML for the two select2 dropdowns is quite similar. Here’s the code for the “From” dropdown:

<select id="from" class="js-example-basic-multiple" multiple="multiple" style="width: 100%">
<?php
 echo GetPeople('F');
 ?>
</select>

GetPeople is a PHP function that calls out to the database and then converts the returned data to a series of lines. The parameter indicates whether to get the “From” data or the “To” data. That parameter is also used as part of the ID for each item (because it turns out that if options with the same ID appear in different select2 controls, things go downhill fast).

function GetPeople ($type) {
    $people = getdata("GetPeople", "'$type',''", "Couldn't retrieve list of people.<br/>");
    $return = '';
    while ($obj = mysqli_fetch_object($people)) {
        $return .= "<option value='" . $obj->FullName . "' id='" . $type . $obj->iid . "'>" . $obj->FullName . "</option>";
    }
    
    return $return;
}

The OnChange event for each of the select2 controls calls a JS function called updatePeople, passing either ‘F’ or ‘T’ to indicate which select2 needs its contents updated. That is, the From dropdown passes ‘T’ and the To dropdown passes ‘F’.

updatePeople uses AJAX to go out and collect the data, build a new set of lines and sub them into the specified control. That’s all working as expected. But doing so leaves that control with no items selected. When I try to restore the selections the control had before the update, nothing happens. Here’s the code for updatePeople, including my attempt to restore the selection:

function updatePeople(cwhich) {
    var results = '';
    var success = false;
    //get the currently selected list for the other dropdown, too
    //so we can use them to restore selections later

    if (cwhich == "F") {
       var chosen = getChoices('#to');
       var selecteditems = getChoices('#from',true);
    } else {
       var chosen = getChoices('#from');
       var selecteditems = getChoices('#to',true);
    }

    var filters = cwhich + "','" + chosen + "'";
    var fnargs = "GetPeople|'" + filters;

    $.ajax({
       url: 'retrievedata.php',
       type: "POST",
       async: false,
       data: {"functionname": "getpeople", "arguments": fnargs},
       dataType: "JSON",
       success: function (obj) {
          if (cwhich=="F") {
             var target = "#from";                        
          } else {
             var target = "#to";
          }

          if ((obj===null)) {
             //clear dropdown
             $(target).html('');
          }
          else {                           
             //build the list of options
             var options = '';
             for (line = 0; line < obj.length; line++) {
                options += "<option value='" + obj[line].FullName + "' id='" + cwhich + obj[line].iid + "'>" + obj[line].FullName + "</option>";
             }

             window.allowupdate = false;
             $(target).html(options);

             //turn list of selected items into array
             var arrSelected = selecteditems.split(',');
             $(target).val(arrSelected);
             $(target).trigger('change');
             window.allowupdate = true;

          }                    
          success = true;
       },
       error: function (textStatus, errorThrown) {
          success = false;
          $("#testresult").text('Error occurred: '.textStatus);
          console.log('Error occurred: '.textStatus);
       }
    });

 }

The window.allowupdate bit is because trying to change the selections for one dropdown would fire its OnChange, and that would change the first one. So I added a flag that’s checked in the OnChange code, so that I can change one without changing the other.

What I’m looking for is how to set the modified select2 control to have the same items selected as before updating the contents of the control.

TIA,
Tamar

Solved my own problem. There were two issues:

  1. Setting the control’s HTML seemed to make it unhappy. I changed that code to first disconnect from select2, then update the HTML, then reconnect to select2:
$(target).select2('destroy');
$(target).html(options);
$(target).select2({placeholder: 'Anyone (or choose senders)'});
  1. I didn’t have the right value to reset the selections. My code was retrieving the primary keys for the selected items, but I needed their actual contents, which I was able to retrieve by calling the control’s val function.