3
\$\begingroup\$

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/

Mainly, it is about this piece of code:

    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";
            tdDel.addEventListener("click", delItem, false);
            tr.appendChild(tdDel);

            placeHolder.appendChild(tr);
        }
    };
}

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

    // What do I have to do here?
}
\$\endgroup\$
2
  • 3
    \$\begingroup\$ 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 \$\endgroup\$ Nov 2 '13 at 18:42
  • \$\begingroup\$ @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! \$\endgroup\$ Nov 2 '13 at 19:27
2
\$\begingroup\$

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;
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.