john
john

Reputation: 707

Why is DOM not getting modified when selecting an option from select list?

I have a simple example here. It's an "all in one" HTML with js and CSS file.

I'm using DataTables responsive theme.


Here are the problem replication steps:

  1. Save the below code into a html file

  2. Open this file in Chrome browser

  3. Reduce the size of the browser so that the fourth field is not visible

  4. Click the green "+" expansion button

  5. Select any value

  6. Click the green "+" button to collapse

  7. Click the green "+" button again to expand

  8. The value you selected is not actually selected

WHY??


   <html>
    <head> 
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script> 
    <script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script> 
    <script src="https://cdn.datatables.net/responsive/2.2.1/js/dataTables.responsive.min.js"></script>  
    
    <link rel="stylesheet" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css">
    <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.1/css/responsive.dataTables.min.css">
    
    <script> 
    $(document).ready(function() {
        $('#example').DataTable();
    } );
    </script> 
    
    	 
    </head> 
    
    <body>
    
    <table id="example" class="display responsive nowrap" style="width:100%">
            <thead>
                <tr>
                    <th>First name</th>
                    <th>Last name</th>
                    <th>Position</th>
                    
                    <th>Weird JQuery Behaviour</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Tiger</td>
                    <td>Nixon</td>
                    <td>System Architect</td>
                    
                    <td>
    				
    				<select>   
    				<option value="123">123</option> 
    <option value="345">345</option> 
    <option value="456">456</option> 
    <option value="567">56</option> 
    <option value="678">67</option> 
    <option value="789">789</option> 				
    				</select>
    				
    				</td> 
    				
                </tr>
               
    		   
    
     
            </tbody>
        </table> 
    	
    	</body> 
    	</html> 

enter image description here

I MUST keep the selected entry to show up as selected. How can I do this?

Upvotes: 3

Views: 365

Answers (2)

Julien Gr&#233;goire
Julien Gr&#233;goire

Reputation: 17144

There's a rendering engine that recreates elements each time there's a column shown or hidden. So obviously the select element inner state doesn't follow.

You can access the rendering function and modify it so as to create a link. The function is callable in datable options like this:

responsive: {
    details: {
        renderer: function ( api, rowIdx, columns ) 

The render is called for each row that is shown or hidden. So it's called when you click the plus sign, or when the columns are wide enough to show the original column. You can in that function build the elements that are going to be added and set the proper index on the select element. But since it's a different select, you'll need to track the changes made on it so as to update the original as well. Something like this:

$(document).ready(function() {
  $('#example').DataTable({
    responsive: {
      details: {
        renderer: function(api, rowIdx, columns) {
          // normally the render is only the data part, and then you return data
          var data = $.map(columns, function(col, i) {
            return col.hidden ?
              '<tr data-dt-row="' + col.rowIndex + '" data-dt-column="' + col.columnIndex + '">' +
              '<td>' + col.title + ':' + '</td> ' +
              '<td>' + col.data + '</td>' +
              '</tr>' :
              '';
          }).join('');
          
          // this is the custom part in which you manipulate the data before it is returned
          if (data) {
            var el = document.createElement('div');
            el.innerHTML = data;
            // here you set your new select element to the same index as the original one
            el.querySelector('select').selectedIndex = api.cell({
              row: rowIdx,
              column: 3
            }).node().querySelector('select').selectedIndex;
            
            // you need to track changes on this new one to update original
            el.querySelector('select').addEventListener('change', function(e) {

              api.cell({
                row: rowIdx,
                column: 3
              }).node().querySelector('select').selectedIndex = e.target.selectedIndex;
            });
            // you return a table with your element, which is the same as with the original
            // render, but with the select set to proper index
            return $('<table/>').append(el);
            
          // this is also part of the original. This is called when no column is hidden
          // you return nothing and so your element is removed 
          } else {
            return false;
          }

        }
      }
    }
  });

});
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/responsive/2.2.1/js/dataTables.responsive.min.js"></script>

<link rel="stylesheet" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.1/css/responsive.dataTables.min.css">
<table id="example" class="display responsive nowrap" style="width:100%">
  <thead>
    <tr>
      <th>First name</th>
      <th>Last name</th>
      <th>Position</th>

      <th>Weird JQuery Behaviour</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tiger</td>
      <td>Nixon</td>
      <td>System Architect</td>

      <td>

        <select>
          <option value="123">123</option>
          <option value="345">345</option>
          <option value="456">456</option>
          <option value="567">56</option>
          <option value="678">67</option>
          <option value="789">789</option>
        </select>

      </td>

    </tr>

    <tr>
      <td>Tiger</td>
      <td>Nixon</td>
      <td>System Architect</td>

      <td>

        <select>
          <option value="123">123</option>
          <option value="345">345</option>
          <option value="456">456</option>
          <option value="567">56</option>
          <option value="678">67</option>
          <option value="789">789</option>
        </select>

      </td>

    </tr>



  </tbody>
</table>

Upvotes: 3

Quentin
Quentin

Reputation: 944169

Why is DOM not getting modified when selecting an option from select list?

It is … but it updates the current value of the select element, not its default value.

The value you selected is not actually selected. Why?

Presumably (and I'm not going to go digging through the minified source code you linked to in order to be sure), the library reads the innerHTML of the table and rewrites it.

It doesn't store the current value of the select (which isn't serialized to the innerHTML) so when it writes it back, the select is reset to its default value.

Upvotes: 5

Related Questions