Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

ilovecode
ilovecode
8,071 Points

Why is this.image a problem?

I have code that is getting long and decided to create classes to practice classes and also organise my code.

There is something I don't understand. I have a .json file with a few products on and I generate a product listing body for each product using a fetch API and map through the results to display the product.

When I created the class everything worked, except for the images. I created a method to build the product listing called productBody(). The correct product names. ids, descriptions etc are being returned correctly except the image name, and I don't understand why. I get a 404 error saying the image does not exist. But when I insert a parameter for image in productBody() then it works when I call it. I don't understand why.

I am going to paste two sections of code. The first code is my current code that is the class. The second will be the old code, before I created the class.

fetch(products)
    .then(response => response.json())
    .then(data => generateProduct(data));

function generateProduct(data) {
    let prod = data.map(dat => {
        productView = new Product(dat.shop, dat.id, dat.product, dat.description, dat.price, dat.stock, dat.stockLeft, dat.image);
        console.log(dat.image);
        return row.innerHTML = productView.productBody();
    });
    row.innerHTML = prod.join('');
}

class Product {
    constructor(shop, id, product, description, price, stockLeft, image) {
        this.shop = shop;
        this.id = id;
        this.product = product;
        this.description = description;
        this.price = price;
        this.stock = true;
        this.stockLeft = stockLeft
        this.image = image;
    }

     //when I insert 'image' as a parameter and insert 'image' inside the img tags then the image displays.
    productBody() {
        return `<div id="product-${this.id}" class="col-md-4 col-sm-12">
            <div class="shop-list">
                <a class="product-image">
                    <img src="../images/shops/${this.image}" class="img-fluid" alt="${this.product}">
                </a>
                <h4 class="product-name">${this.product}</h4>
                <button class="details">Click for more details</button>
                <button class="addToTrunk">Add to trunk</button>
            </div>
        </div>`;
    };
}

Second code:

fetch(products)
    .then(response => response.json())
    .then(data => generateProduct(data));

function generateProduct(data) {
    let prod = data.map(dat => {
        return row.innerHTML = `<div id="product-${dat.id}" class="col-md-4 col-sm-12">
                            <div class="shop-list">
                                <a class="product-image">
                                    <img src="../images/shops/${dat.image}" class="img-fluid" alt="${dat.product}">
                                </a>
                                <h4 class="product-name">${dat.product}</h4>
                                <button class="details">Click for more details</button>
                                <button class="addToTrunk">Add to trunk</button>
                            </div>
                        </div>`;
    });
    row.innerHTML = prod.join('');
    generateProductDetails(data);
}

2 Answers

Hi ilovecode,

I think your issue is due to the fact that when you call new Product(), you’re currently passing in more arguments than your constructor function is set up to accept/use. You’re passing in both dat.stock and dat.stockLeft, but your constructor function doesn’t have a stock parameter. So dat.stock is being used as the stock variable within your Product class definition, and dat.stockLeft is being used as the image variable within your Product class definition.

Take a look at that, and see if that helps you get back on track. If not, let me know, and I’ll take a deeper dive into what other potential issues may exist.

ilovecode
ilovecode
8,071 Points

That was it thanks!!! But now I have a dilemma... I have many arguments that I am passing when I instantiate my class. I see a potential problem in the future. I have several functions where I want to use the class and if I have to type out each argument it is going to become time consuming. Is there a way to pass in one argument in "product View"?

When you say you have several functions where you want to use the class, can you give me an example? I’m having a little trouble visualizing what you mean.

Are you saying there are methods within the class that you’re wanting other objects (that aren’t productView) to be able to take advantage of? Or maybe you’re saying that you want to pass a Product instance into a function as an argument? Or maybe you’re saying that you want to create a subclass that’s an extension of the Product class?

ilovecode
ilovecode
8,071 Points

Brandon White let's say I have the function generateProduct (like above) and I create more functions, e.g generateShop, generateCart or anything in those lines. In each function I want to use the same class and I insert the following inside each function (note that the arguments will not be dat.shop in each case, it can be data[i].shop or so)

productView = new Product(dat.shop, dat.id, dat.product, dat.description, dat.price, dat.stock, dat.stockLeft, dat.image);

But if you look at my class I created above, I see potential issues in the future where I might add more items to my constructor, e.g barCode, shopID or anything. But then I am going to have to go to each function where I instantiated the Product class and add those items on each function. What if I have 20 functions that use this?

So my question is is there a way to insert one argument for many, like new Product(haveManyArgs).