0

I have a table with multiple cells containing select boxes. The code I have can create/delete rows relative to the entry which you click "+/-" from. I would like it so that if I press "+" then my program will look at the employee chosen in the above entry and have it as the selected value in the current (or new) entry.

I am having a hard time grabbing the value of the field, as well as making it the selected value.

Here is my code:

[JS]

function createRow(id, emp = null) {
  var newrow = [
    id,
    '<select class="browser-default custom-select">' + employee_list + '</select>', // Want to add 'emp' here as selected element
    '<select class="browser-default custom-select"></select>',
    '<div class="input-group"><input type="number" min="0" step="0.5" class="form-control"><div class="input-group-append"><span class="input-group-text">hours</span></div>',
    '<div class="input-group"><div class="input-group-prepend"><span class="input-group-text">$</span></div><input type="number" step="0.01" min="0" class="form-control"></div>',
    '<textarea class="form-control" maxlength="200"></textarea>',
    '<a class="addButton"><i class="fa fa-plus"></i></a>&nbsp;&nbsp;&nbsp;<a class="deleteButton"> <i class="fa fa-minus"></i></a>'
  ];

  return '<tr><td>' + newrow.join('</td><td>') + '</td></tr>';
}

function renumberRows() {
  $('table#budget tbody tr').each(function(index) {
    $(this).children('td:first').text(index + 1);
  });
}

$('#add').click(function() {
  var lastvalue = 1 + parseInt($('table#budget tbody').children('tr:last').children('td:first').text());
  $('table#budget tbody').append(createRow(lastvalue));
});

$('table#budget').on('click', '.addButton', function() {
  $(this).closest('tr').after(createRow(0));
  console.log($(this).closest('tr').children('td:nth-child(2)').val()); // tring to get previous entries selected employee
  renumberRows();
}).on('click', '.deleteButton', function() {
  $(this).closest('tr').remove();
  renumberRows();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="pure-table pure-table-horizontal" id="budget" style="width: 100%" cellpadding="0" cellspacing="0">
  <thead>
    <tr>
      <th>Row</th>
      <th>Employee</th>
      <th>Task</th>
      <th>Budget</th>
      <th>Expense</th>
      <th>Comments</th>
      <th><a id="add" style="float: right; color: #0000EE">Add Row <i class="fa fa-plus"></i></a></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>
        <select class="browser-default custom-select" id="emp" size="1">
          <option disabled selected>Choose Employee</option>
          <?php for($i=0;$i<count($options_2);$i++){echo $options_2[$i];} ?>
        </select>
      </td>
      <td>
        <select class="browser-default custom-select" id="task" size="1">
          <option disabled selected>Pick Employee</option>
        </select>
      </td>
      <td>
        <div class="input-group">
          <input type="number" min="0" step="0.5" class="form-control">
          <div class="input-group-append">
            <span class="input-group-text">hours</span>
          </div>
      </td>
      <td>
        <div class="input-group">
          <div class="input-group-prepend">
            <span class="input-group-text">$</span>
          </div>
          <input type="number" step="0.01" min="0" class="form-control">
        </div>
      </td>
      <td><textarea class="form-control" maxlength="200"></textarea></td>
      <td><a class="addButton"><i class="fa fa-plus"></i></a>&nbsp;&nbsp;&nbsp;
        <a class="deleteButton"> <i class="fa fa-minus"></i></a>
      </td>
    </tr>
    <!-- This is our clonable table line -->
  </tbody>
</table><br>

example enter image description here

The expected result would be to have the employee of the previous (or above) entry as the selected value in the new row upon clicking +. Or in the photo, the blacked out name would be showing where Choose Employee is.

EDIT: the global variable employee_list is an array containing all of the employees in html options format.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • I don't see the + you referenced a few times. Is this all your code? – shadow2020 Jun 11 '19 at 17:45
  • @shadoe2020 the plus can be seen in the image I just added. It is the last column in the table. It is `class="addButton"` in the code –  Jun 11 '19 at 17:46
  • `.children('td:nth-child(2)').val()` - A `` element doesn't have a "value". Did you just forget to look for the ` – David Jun 11 '19 at 17:46
  • @David ah, yes that is part of the problem. But I still need to be able to set that value as selected. –  Jun 11 '19 at 17:49
  • @Jordan: Where do you try to do that? Does that attempt have the same problem? – David Jun 11 '19 at 17:50
  • @David in the createRow function there is a comment beside the array element that I think I need to manipulate. I'm not quite sure what selector I need to access the value yet. –  Jun 11 '19 at 17:53
  • @Jordan: The `createRow` function doesn't actually add anything to the DOM though. It just returns a string. *After* that string is added to the DOM as new HTML then you can select your `` element you're targeting. When you examine your resulting HTML, how would you identify it? I imagine it's similar to the technique you already use with `.closest()` and `.children()` and other DOM traversal functions. – David Jun 11 '19 at 17:57
  • @David I think i'd probably identify it with the row number. temporarily saving the new index in the `renumberRows` function and searching for it based on that newly created index. –  Jun 11 '19 at 18:02

1 Answers1

0

It would be easier if createRow() converted the HTML to DOM elements. Then you can use jQuery methods to find the select and set its value.

Use $(this).closest('tr').find('select:first').val() to get the employee from the row where you clicked Add.

It would also be a good idea to add distinct classes to specific inputs and selects, rather than using selectors like select:first to find a particular select in the row.

function createRow(id, emp = null) {
  var newrow = [
    id,
    '<select class="browser-default custom-select">' + employee_list + '</select>', // Want to add 'emp' here as selected element
    '<select class="browser-default custom-select"></select>',
    '<div class="input-group"><input type="number" min="0" step="0.5" class="form-control"><div class="input-group-append"><span class="input-group-text">hours</span></div>',
    '<div class="input-group"><div class="input-group-prepend"><span class="input-group-text">$</span></div><input type="number" step="0.01" min="0" class="form-control"></div>',
    '<textarea class="form-control" maxlength="200"></textarea>',
    '<a class="addButton"><i class="fa fa-plus"></i></a>&nbsp;&nbsp;&nbsp;<a class="deleteButton"> <i class="fa fa-minus"></i></a>'
  ];
  var elts = $('<tr><td>' + newrow.join('</td><td>') + '</td></tr>');
  if (emp !== null) {
    elts.find("select:first").val(emp);
  }
  return elts;
}

function renumberRows() {
  $('table#budget tbody tr').each(function(index) {
    $(this).children('td:first').text(index + 1);
  });
}

$('#add').click(function() {
  var lastvalue = 1 + parseInt($('table#budget tbody').children('tr:last').children('td:first').text());
  $('table#budget tbody').append(createRow(lastvalue));
});

$('table#budget').on('click', '.addButton', function() {
  var prevemp = $(this).closest('tr').find('select:first').val();
  $(this).closest('tr').after(createRow(0, prevemp));
  console.log($(this).closest('tr').children('td:nth-child(2)').val()); // tring to get previous entries selected employee
  renumberRows();
}).on('click', '.deleteButton', function() {
  $(this).closest('tr').remove();
  renumberRows();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="pure-table pure-table-horizontal" id="budget" style="width: 100%" cellpadding="0" cellspacing="0">
  <thead>
    <tr>
      <th>Row</th>
      <th>Employee</th>
      <th>Task</th>
      <th>Budget</th>
      <th>Expense</th>
      <th>Comments</th>
      <th><a id="add" style="float: right; color: #0000EE">Add Row <i class="fa fa-plus"></i></a></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>
        <select class="browser-default custom-select" id="emp" size="1">
          <option disabled selected>Choose Employee</option>
          <?php for($i=0;$i<count($options_2);$i++){echo $options_2[$i];} ?>
        </select>
      </td>
      <td>
        <select class="browser-default custom-select" id="task" size="1">
          <option disabled selected>Pick Employee</option>
        </select>
      </td>
      <td>
        <div class="input-group">
          <input type="number" min="0" step="0.5" class="form-control">
          <div class="input-group-append">
            <span class="input-group-text">hours</span>
          </div>
      </td>
      <td>
        <div class="input-group">
          <div class="input-group-prepend">
            <span class="input-group-text">$</span>
          </div>
          <input type="number" step="0.01" min="0" class="form-control">
        </div>
      </td>
      <td><textarea class="form-control" maxlength="200"></textarea></td>
      <td><a class="addButton"><i class="fa fa-plus"></i></a>&nbsp;&nbsp;&nbsp;
        <a class="deleteButton"> <i class="fa fa-minus"></i></a>
      </td>
    </tr>
    <!-- This is our clonable table line -->
  </tbody>
</table><br>
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Awesome, that worked flawlessly thank you. Where should I do an ajax call to update the options of the select box to the right of the employee select box? –  Jun 11 '19 at 18:17
  • Use an event handler on whatever element that select box depends on to make the AJAX call. – Barmar Jun 11 '19 at 18:19
  • The dependant is the employee name. I've tried using synchronous ajax calls and repeating your solution here with the data recieved from that but I can't see to append the options to `elts.find("select:nth-child(2)").append(...`. Do you have any recommendations? –  Jun 11 '19 at 19:07
  • First of all, see https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements for how to delegate an event handler to the dynamically-created selects. – Barmar Jun 11 '19 at 19:20
  • Then see https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback for how to refer to the `this` element from the original event in the AJAX callback function, so you don't have to use synchronous AJAX. – Barmar Jun 11 '19 at 19:21
  • And it would be a good idea to assign classes to the selects so you don't need things like `:nth-child(2)`. – Barmar Jun 11 '19 at 19:22