Multiple select that could work on my select

Hello, I’m no expert. And I’m kinda of struggling with Javascript.
I want to make a custom select, or I don’t know what exactly.

I’ve done a table that you can add rows, to add users with their roles to database. But before adding a user, you have a filter on wich you select the role, if user has email “@example.” then you get certains roles for it, else if it has other emails on it, it gives some other role options, and some checkboxes.

So this is my
css:

      .iroles, .eroles, .iroles1, .eroles1{
        display: none;
      }
      .ndaDiv {
        display: none;
      }

Html

    <div class="mb-3 mt-5 w-100">
    <input class="btn btn-success mb-3 btnrad fw-bold" type="button" id="addbutton" value="+ User" title="Add more input rows">
    <table class='skillTable' id="usertable" width="100%" border="0">
        <tr>
          <td class="w-50"><b>User email: </b></td>
          <td class="w-25"><b>User role:</b></td>
        </tr>
      </table>  
    </div>
    
   <!-- This is hidden only apears if certain roles are selected -->
    <div class="mt-5 ndaDiv" id="ndaDiv">
    <label for="user-email"><h6>Confirmation</h6></label>
      <div class="mb-3">
        <input id="checkId" type="checkbox" name="nda" class="form-check-input nda">    
      </div>
      <div class="mb-3 mt-5 code">
        <label for="site-code"><h6>Code</h6></label>
        <input id="pocothers" class="form-control input-sm w-50 mt-2" type="email" name="code" pattern="[a-zA-Z0-9._%+-]+@[a-z0-9.-]+\.[a-zA-Z]{2,4}" maxlength="45" style="text-transform: lowercase">
      </div> 
    </div>

my js:

<script type="text/javascript">
      // Add rows
      let i = 0; 
    $("#addbutton").click(function () {
        $("#usertable").append('<tr>'+
        '<td><input id="email" class="form-control email'+i+'" type="email" name="useremail[]" required pattern="[a-zA-Z0-9._%+-]+@[a-z0-9.-]+\.[a-zA-Z]{2,4}" maxlength="45" style="text-transform: lowercase"/></td>'+
        '<td>'+
          '<select class="form-select skillSelect" name="role[]" id="dropRoles" required/>'+
              '<option class="blank'+i+'" value=""></option>'+
            '<optgroup id="internal'+i+'" Class="iroles" label="Internal Roles">'+
                '<option value="role 1">role 1</option>'+
                '<option value="role 2">role 2</option>'+
                '<option value="role 3">role 3</option>'+
                '<option value="role 4">role 4</option>'+
                '<option value="role 5">role 5</option>'+
            '</optgroup>'+
            '<optgroup id="external'+i+'" class="eroles" label="External Roles">'+
                '<option value="role 6">role 6</option>'+
               '<option value="role 7">role 7</option>'+
               '<option value="role 8">role 9</option>'+
            '</optgroup>'+
          '</select>'+  
        '</td>'+
        '<td><button type="button" class="removebutton rounded-circle" title="Remove this row">X</button></td></tr>').find("input").each(function () {
    });
    i++;
    if(i == 20){ // If row count equal to this number then disable button
    $("#addbutton").attr('disabled','disabled');
    }
    });;
    
    //Remove button from append
    $(document).on('click', 'button.removebutton', function () {
      $(this).closest('tr').remove();
        checkExtras(); // Remove nda when remove button is clicked
        return false;
    });
    
    // On page load click addbutton
    window.onload=function(){
      document.getElementById("addbutton").click();
    };
    </script>
    
    <script type="text/javascript">
    // Match email
    for(let i = 0; i <= 20; i++)
    {
      $(document).on("keyup change", `.email${i}`, function() {
        if ($(this).val().match(/@example[.]/i)){
          $(`#internal${i}`).show();
          $(`#external${i}`).hide();
          $(`.blank${i}`).hide();
        } else {
          $(`#internal${i}`).hide();
          $(`#external${i}`).show();
          $(`.blank${i}`).hide();
        }
      });
      // Set a blank value when edit email
      $(document).on('keyup change', `.email${i}`, function() {
          $(this).closest('tr').find(`.blank${i}`).prop('selected', true);
          checkExtras();
      });
    }
    </script>
    
    <script type="text/javascript">
    // On select change on this table, checkExtras()
    $('.skillTable').on('change', ".skillSelect", function() {
      checkExtras();
    })
    
    // Decides if nda is added or not
    function checkExtras() {
      let hasExtras = false;
      $(".skillSelect").each(function(i, o) {
        let optgroup = $(o).find(':checked').closest('optgroup').attr('label');
        if (optgroup === 'External Roles') hasExtras = true;
    
      })
      $(".ndaDiv").toggle(hasExtras);
      if ($('.ndaDiv').is(":visible") != true) { // If the ndaDiv is not visible then remove required / else add required
        $("#checkId").removeAttr('required');
        $("#pocothers").removeAttr('required');        
      } else {
        $("#checkId").attr('required', '');
        $("#pocothers").attr('required', '');
      }
    }
    </script>

But now I want to add multiple roles, I want to be able to pick more than one role and see it on the select like role 1, role 4, etc. Depending on what you pick.

I’ve tried to use the html multiple but it dosen’t show up as I was expecting to, then I’ve tried some multiple plugins but the also don’t work with my code. I’m guessing maybe my code is not good, I was thinking in doing my own custom multiple but It dosen’t seem so easy, any ideas or alternatives of what I could do? I accept any suggestions, stuff to read about, etc.

Thanks a lot.

There are multiple problems with your code but I guess a good start is to do not use the same I’d on multiple elements. Id‘s must be unique.
By now, if you add a new row, you add a new input with id „email“ and a new select with Id „dropRoles“. Add an index variable which you increase every time the click function is called and add this to the id‘s

id = "emails_' + index + '"
1 Like

This is the second time this year I have seen this assignment.

The key to simplifying all the code and to get it to work for the correct dynamically added section is to eliminate all the numerically suffixed ids/classes, the loop running code for that numerically suffixed markup, and eliminate unneeded ids throughout the repeated markup. You will just use static class names - “email”, “blank”, “iroles”, or “eroles” and use the same technique found in the remove button javascript to find and operate on the specific instance of markup.

For example, your // Match email logic would become -

<script>
$(document).on('keyup change', '.email', function() {
	if ($(this).val().match(/@example[.]/i)){
		$(this).closest('tr').find('.iroles').show();
		$(this).closest('tr').find('.eroles').hide();
		$(this).closest('tr').find('.blank').hide();
	} else {
		$(this).closest('tr').find('.iroles').hide();
		$(this).closest('tr').find('.eroles').show();
		$(this).closest('tr').find('.blank').hide();
	}
});
</script>

No looping, no i variables, no concatenation, no extra ids.

1 Like

Not an expert with Jquery but couldn’t you use toggle instead?

$(document).on('keyup change', '.email', function() {
	const matches = $(this).val().match(/@example[.]/i)
	
	$(this).closest('tr').find('.iroles').toggle(matches);
	$(this).closest('tr').find('.iroles').toggle(!matches);
	$(this).closest('tr').find('.iroles').hide();
});

Toggle accepts a boolean value, so if true will show and false will hide.
https://api.jquery.com/toggle/

1 Like

Once you simplify the code, so that the actual problem can be seen -

To make the multiple attribute work and match up with the corresponding email[] field values, you need to change the select name attribute to a two dimensional array (and also add the multiple attribute) -

name="role['+i+'][]"
1 Like

Hello ppl, thanks a lot for your answers. I will read everything in detail, and I will start redoing what I’ve done so far.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.