Dynamic Sortable Table using Backbone.js
by helgatheviking
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div id="container">
</div>
<button id="add-product">Add</button>
<script type="text/template" id="products-table">
<table id="my-table">
<thead>
<tr>
<th>Product</th>
<th>Quantity</th>
<th> </th>
</tr>
</thead>
</table>
</script>
<script type="text/template" id="product-row">
<td class="product-title">
<%= title %>
</td>
<td class="product-quantity">
<input type="number" name="data[<%= product_id %>][quantity]" value="<%= quantity %>" />
</td>
<td class="product-remove">
<a class="delete-product " href="#">Remove</a>
</td>
</script>
CSS
table {
border-collapse: collapse;
margin-bottom: 1em;
}
th,
td {
border: 1px solid black;
font-size: 1em;
font-family: Arial;
padding: .25em;
}
input { width: 4em; text-align: center; }
tr.ui-sortable-handle { cursor: move; }
JavaScript
var myApplication = {};
(function($, myApplication) {
// Model
myApplication.Product = Backbone.Model.extend({
defaults: {
"quantity": 1,
"title": "",
"product_id": ""
}
});
// Collection
myApplication.ProductsCollection = Backbone.Collection.extend({
model: myApplication.Product,
el: "#container"
});
// Singular Row View
myApplication.productView = Backbone.View.extend({
model: myApplication.Product,
tagName: 'tr',
events: {
'click .delete-product': 'removeProduct',
'change .product-quantity :input': 'setQuantity'
},
// Get the template from the DOM.
template: _.template($("#product-row").html()),
// Render the single model.
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
// Remove/destroy a model.
removeProduct: function(e) {
e.preventDefault();
this.model.destroy();
myApplication.productList.render();
},
// Persist the quantity in the model.
setQuantity: function(e) {
value = this.$el.find('.product-quantity :input').val();
this.model.set('quantity', value);
}
});
// List View
myApplication.productListTable = Backbone.View.extend({
el: "#container",
template: _.template($("#products-table").html()),
addSingle: function(model) {
var view = new productView({
model: model
});
this.$el.find('tbody').prepend(view.render().el);
},
// Callback for SelectWoo sectionn
addProduct: function(event, attributes) {
Product = new myApplication.Product(attributes);
this.collection.add(Product, {
at: 0
});
this.render();
},
events: {
'click .delete-product': 'removeProduct',
'addFreeGiftProduct': 'addProduct',
},
render: function() {
this.$el.children().remove();
if (this.collection.length) {
...