# Deleting a table row in JavaScript with OOP

I started learning OOP in JavaScript at school and I have to do my homework in OOP. It is a shopping list, one fills in a product and price and that is put into an array, the array its contents are put in a table in HTML. The list also has got delete buttons for every product, I have thought about using this in JavaScript, as I am working in OOP, but I am sceptic because of the scope.

The idea is that one clicks "verwijder" on the webpage (EDIT: in the corresponding row) and the table row is gone. I have thought about using this but also about dynamically updating the table after removing the selected row from the array.

Who can advise me about what to do and how to do that correctly? I have uploaded my JavaScript here: http://jsfiddle.net/hNAZ9/

    function ShoppingList(){
this.items = [];
this.setItem = function(product, price){
var item = new Item(product, price);
this.items.push(item);
};
this.render = function(){
var placeHolder = document.getElementById("shoppingList");
placeHolder.innerHTML = "";

for(var i = 0; i <this.items.length; i++){
var tr = document.createElement("tr");
tr.id = i;

var tdProduct = document.createElement("td");
tdProduct.innerHTML = this.items[i].product;
tr.appendChild(tdProduct);

var tdPrice = document.createElement("td");
tdPrice.innerHTML = this.items[i].price;
tr.appendChild(tdPrice);

var tdDel = document.createElement("td");
tdDel.innerHTML = "Verwijder";
tr.appendChild(tdDel);

placeHolder.appendChild(tr);
}
};
}

function delItem(e){
e.preventDefault();

// What do I have to do here?
}

• You actually have a decent start right there with proper separation of concerns - actually better than most code I see in the web so for starters - good work. Some things I'd do differently: - That getElementById call inside .render is not needed. You can make that DOM query once and then have a reference to that element. Also, the function you're looking for for removing elements from the array is .splice Nov 2 '13 at 18:42
• @BenjaminGruenbaum: Wow, thank you for your response, I am glad to hear that you are very content. :) I will look into the getElementById inside of .render and I will also look into the function .splice and its usage. Thank you a lot for your very helpful comment! Nov 2 '13 at 19:27

The trick is linking a row to its item object and vice-versa, so both are removed/added in lockstep.

There are a lot of ways of going about that, but given your original code, the following should be a pretty good way to go.

I'd suggest using a closure when defining the event handler to make things simpler. Here's a simple demo and here's the code

function ShoppingList() {
var that  = this, // keep a scope reference
table = document.getElementById("shoppingList"); // find this once (only works if the page has been loaded already)

this.items = [];

// this adds an item to the array and a row to the table
this.addItem = function (product, price) {
var item = new Item(product, price);
this.items.push(item);
table.appendChild(buildRow(item));
};

// this removes the given item from the array and the table
this.removeItem = function (item) {
for(var i = 0 ; i < this.items.length ; i++) {
if(this.items[i] === item) {
this.items.splice(i, 1);
break; // skip the rest of the loop, since we've found what we need
}
}
table.removeChild(item.row); // remove the row
}

// this isn't actually needed as rows get added by addItem,
// but it'll work just fine regardless
this.render = function(){
table.innerHTML = "";
for(var i = 0; i < this.items.length; i++){
table.appendChild(buildRow(this.items[i]));
}
};

// an internal helper. This can be moved to the Item prototype
// since it's not actually dependent on anything in ShoppingList
function buildRow(item) {
// an internal, internal helper
function buildCell(text) {
var td = document.createElement("td");
td.innerHTML = text;
return td;
}

// store the table row object on the item itself
item.row = document.createElement("tr");

item.row.appendChild(buildCell(item.product));
item.row.appendChild(buildCell(item.price));

var deleteCell = buildCell("Verwijder");
item.row.appendChild(deleteCell);

// set the event listener here, where we can access item and tr
deleteCell.addEventListener("click", function () {
that.removeItem(item); // remove the item. Here we need the that var
}, false);

return item.row;
}
}