1

Whenever the user clicks on a value in the drop down, I want to create a table with the values in it. When you unchecked the checkbox, it should dissapper from the table. The problem that I have is that, it keeps appending the selection like this:

enter image description here

This is how it should look like:

enter image description here

This is my asp code. I also would like to target a specific table by it's ID. because I'll have about 20 dropdown in this page.

<asp:ListBox ID="ddlRolePosition" AutoPostBack="false" runat="server"
     SelectionMode="Multiple" class="selectpicker show-tick form-control show-tick"
     multiple data-validation-event="change" style="display: none;">
</asp:ListBox> 

<table>
  <tbody>
  </tbody>
</table>
$("[id$=ddlRolePosition]").change(function() {
  if (!$("[id$=ddlRolePosition]").val()) {

  }
  else {
    var markup = "<tr><td>" + $("[id$=ddlRolePosition]").val() + "</td></tr>";
    $("table tbody").append(markup);
  }
});
5
  • i think you should reset the table onchange then fill it again Commented Nov 12, 2019 at 18:38
  • You're appending your markup to the table. That's what append does. It adds to what's already there. Maybe use innerHTML instead? Commented Nov 12, 2019 at 18:45
  • i would advice him to refill the whole table by the selected data as if he uses innerHtml he will end doing the same... Commented Nov 12, 2019 at 18:49
  • You want a table, or a list? Commented Nov 12, 2019 at 18:52
  • a table or list, it doesnt matter TBH. Commented Nov 12, 2019 at 20:05

2 Answers 2

1

You can:

  1. Wrap the select and table elements so you can access many on a single page
  2. Grab the selected options via select.selectedOptions
  3. Added an empty() method that mimics jQuery.fn.empty
  4. Added a triggerEvent() method that mimics jQuery.fn.trigger

// Add event listeners
Array.from(document.querySelectorAll('.preview-combo select')).forEach(combo => {
  combo.addEventListener('change', onComboChange);
});

// Pre-select some options...
let combo = document.querySelectorAll('.preview-combo select');
combo[0].options[0].selected = true; // First combo, first option
combo[0].options[1].selected = true; // First combo, second option
combo[1].options[1].selected = true; // Second combo, second option
combo[1].options[2].selected = true; // Second combo, third option

// Fire change events (for initial loading only)
Array.from(combo).forEach(combo => triggerEvent(combo, 'change'))

function onComboChange(e) {
  let select = e.target, table = select.parentElement.querySelector('table'),
      values = Array.from(select.selectedOptions).map(opt => opt.value);
  appendRows(table, values);
}
function appendRows(table, values) {
  let tbody = empty(table.querySelector('tbody'));
  values.forEach((value) => {
    let tr = document.createElement('tr'), td = document.createElement('td');
    td.textContent = value; tr.appendChild(td); tbody.appendChild(tr);
  });
  return table;
}
function triggerEvent(el, eventName) {
  var event = document.createEvent('HTMLEvents');
  event.initEvent(eventName, true, false);
  el.dispatchEvent(event);
  return el;
}
function empty(el) {
  var range = document.createRange();
  range.selectNodeContents(el);
  range.deleteContents();
  return el;
}
.preview-combo {
  display: inline-block;
}

.preview-combo select {
  width: 100px;
}
<div class="preview-combo">
  <select multiple>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
  </select>
  <table class="selected-values">
    <tbody><tr><td><em>Results</em></td></tr></tbody>
  </table>
</div>

<div class="preview-combo">
  <select multiple>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
  </select>
  <table class="selected-values">
    <tbody><tr><td><em>Results</em></td></tr></tbody>
  </table>
</div>


jQuery + Bootstrap

Here is an example with jQuery.

(($) => {
  $.fn.selectedValues = function() {
    return this.find('option:selected').map((i, opt) => opt.value).get();
  };
})(jQuery);

$('select').selectpicker(); // Convert to a picker.

// Add event listeners
$('.preview-combo select').on('change', onComboChange);

// Pre-select some options...
let $combo = $('.preview-combo select');
$combo.get(0).options[0].selected = true; // First combo, first option
$combo.get(0).options[1].selected = true; // First combo, second option
$combo.get(1).options[1].selected = true; // Second combo, second option
$combo.get(1).options[2].selected = true; // Second combo, third option

// Fire change events (for initial loading only)
$('.preview-combo select').trigger('change');

function onComboChange(e) {
  let $sel = $(e.target);
  populateTable($sel.closest('.preview-combo').find('table'), $sel.selectedValues());
}
function populateTable($table, values) {
  return $table.find('tbody').empty().append(values.map(value => {
    return $('<tr>').append($('<td>').text(value));
  }));
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.1/css/bootstrap-select.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.1/js/bootstrap-select.min.js"></script>
<div class="container">
  <div class="row">
    <div class="col-sm">
      <div class="preview-combo">
        <select multiple class="form-control">
          <option value="1">Audit Assistant</option>
          <option value="2">Audit Expert</option>
          <option value="3">Auditor</option>
        </select>
        <table class="selected-values">
          <tbody><tr><td><em>Results</em></td></tr></tbody>
        </table>
      </div>
    </div>
    <div class="col-sm">
      <div class="preview-combo">
        <select multiple class="form-control">
          <option value="1">Audit Assistant</option>
          <option value="2">Audit Expert</option>
          <option value="3">Auditor</option>
        </select>
        <table class="selected-values">
          <tbody><tr><td><em>Results</em></td></tr></tbody>
        </table>
      </div>
    </div>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

I also want to add some radio button so when the user select "Auditor", they can also select if it's a good or bad. e.g Auditor (rb) good (rb) bad
1

I'd approach this differently and rather keep an array of selected items and then pass those to a function that should generate the rows of the table.

See example below that can be applied:

let target = document.querySelector('#target');

function generateRows(items) {  
  // clear the rows
  target.innerHTML = '';
  
  let rows = '';
  for(let i = 0; i <items.length; i++) {
     rows += `<tr><td>${items[i]}</td></tr>`;
  }
  
  // append once
  target.innerHTML = rows;
}

document.querySelector('.select').onchange = function (e) {
	let items = [];
	for (var i= 0; i < e.currentTarget.options.length; i++) {
    let opt = e.currentTarget.options[i];

    if (opt.selected) {
      items.push(opt.value);
    }
  }
  
  // pass the selected items to function to generate the rows
  generateRows(items);
};
<select class="select" multiple style="width: 100px;">
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
</select>

<table>
<tbody id="target">
  <tr><td>rows here</td></tr>
</tbody>
</table>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.