JSFiddle - React, Tailwind, and code Playground
HTML
<fieldset><legend>Access Details</legend>
<table id="id_express_table">
<thead>
<tr>
<th scope="col" title="action">Action</th>
<th scope="col" title="protocol">Protocol</th>
<th scope="col" title="src-ip">Source IP</th>
<th scope="col" title="dst-ip">Dest. IP</th>
<th scope="col" title="port">Ports</th>
<th scope="col" title="application">Application</th>
<th scope="col" title="expiration">Expiration</th>
<th scope="col" title="delete">Del</th>
</tr>
</thead>
<tbody>
<tr id="form-0-row" class="dynamic-form row1">
<td>
<select name="form-0-action" id="id_form-0-action">
<option value="allow">allow</option>
<option value="deny">deny</option>
</select>
</td>
<td>
<select name="form-0-protocol" id="id_form-0-protocol">
<option value="tcp">TCP</option>
<option value="udp">UDP</option>
<option value="icmp_echo">ICMP Echo</option>
</select>
</td>
<td><input type="text" name="form-0-src_ip" id="id_form-0-src_ip"> </td>
<td><input type="text" name="form-0-dst_ip" id="id_form-0-dst_ip"> </td>
<td><input type="text" name="form-0-port" id="id_form-0-port" readonly=""></td>
<td><input id="id_form-0-application" type="text" name="form-0-application" maxlength="72" readonly="">
</td>
<td>
<select name="form-0-expiration" id="id_form-0-expiration">
<option value="1 month">1 month</option>
<option value="3 months">3...
CSS
body {
font: 12px monospace;
}
input {
border: 1px solid #ccc;
width: 80px;
}
td {
padding: 0 5px 5px 0;
}
JavaScript
(function($) {
var $express = $('#id_express_table'),
$tbody = $express.children('tbody');
// We'll set all our delegations on $express, which means the number of bindings
// will be the same, no matter how large the table grows
// Add Another
$express.delegate('.add-row', 'click', function(event) {
var $deleteRow = $(event.currentTarget).closest('tr');
// I'm SURE this is not how you want to add rows, I'm just using this as a placeholder
$tbody.children('tr').first().clone().insertBefore($deleteRow);
// Better than using javascript:void() inline
event.preventDefault();
});
// Remove
$express.delegate('.delete-row', 'click', function(event) {
var $thisRow = $(event.currentTarget).closest('tr').remove();
// Does not contain logic to prevent removal of all rows 'cause this is a quick example
event.preventDefault();
});
// Protocol change event
$express.delegate('select[name$="protocol"]', 'change', function(event) {
// Fire a custom event whenever the protocol changes
$(event.currentTarget).closest('tr').trigger('ping');
});
// A custom event to handle the change to ping
$express.delegate('tr.dynamic-form', 'ping', function(event) {
// Put any manner of custom logic in here
console.log('ping handling logic');
});
})(jQuery);