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

Tadjiev Codes
Tadjiev Codes
9,626 Points

Dear Folks, Could someone explain, please why when I try to select the Complications from the dropdown list it shows

Dear Folks, Could someone explain, please why when I try to select the Complications from the dropdown list it shows variable endeavor1 is not defined. I guess because of the function scope , I can't access the variables inside of it? But when I remove the instances of the object through constructor method from inside of this function the output shows but it shows undefined Why? I mean is there a specific another way to output the values of the objects when they're built through constructor? I don't want to use the JSON method so I don't understand why the constructor method is not working to target the properties of the OBject. The link to Workspace: https://w.trhou.se/fuee49tlwd Thanks a lot)

Tadjiev Codes
Tadjiev Codes
9,626 Points

And sometimes the line of code

if (departmentSelection.value === "Complications")

throws an error and sometimes it works so weird behavior? Uncaught TypeError: Cannot read property 'value' of undefined

Before this another kinda shopping cart with arrays only and this selection worked perfectly.

4 Answers

Steven Parker
Steven Parker
231,153 Points

You're quite right, it is indeed a scope issue. "Endeavor1" is not a property created in the object constructor. It is a variable defined at line 37 inside the "initializeStoreItems" function, so it is accessible only from inside that function.

But on line 118 in the "displayStoreItems" items function a template literal tries to access "Endeavor1.Name" "Endeavor1.Category", which causes the error you are seeing.

Also, even if it were accessible it would not contain those properties, since it is assigned to the result of a "push" method which would return only the count of items in the array.

Tadjiev Codes
Tadjiev Codes
9,626 Points

Okay, thank you Mr.Steven,

function displayStoreItems() {


        //Loop through array
        for (var i = 0; i < StoreItems.length; i++) {

            //var tempEL = document.createElement("p");
            var tempStoreItem = StoreItems[i]; //Instead of typing StoreItems[i] every time the array we need, we can assign to a variable and use that to refer
            //to the properties in our object instead
            //The above method is easier as there's like kinda less code



            //Display based on filter

            if (departmentSelection.value === 'Complications') {

                var tempEL = document.createElement("p");
                tempEL.innerText = ernie.name + "" + tempStoreItem.Name + "" + tempStoreItem.Price + "" + tempStoreItem.Quantity + "" +
                    tempStoreItem.MaxPerCustomer + "" + tempStoreItem.Category + "";
                //so because ernie is in global variable outside we can access it here

                //This libe gives it a color
                tempEL.style.border = "1px solid " + '#55AB55';


                //Append to the Div
                outputElement.appendChild(tempEL);


            } // end if

        } //end for loop

    } //end function

Now It actually displays the item even those that are in the function scope. Probably because, I'm accessing through the array

var tempStoreItem = StoreItems[i];

Although, now the output works but how to return the specific full object with all the details without typing each property of it like .Name and all? Would Array.prototype.find() be useful or filtering through array objects? Thanks

Tadjiev Codes
Tadjiev Codes
9,626 Points
class StoreItemss {
        constructor(name, natioanlity, policy) {

            this.name = name;
            this.nationality = natioanlity;
            this.policy = policy;
            this.toString = function() {
                return "This item has a " + this.name + ': ' + this.nationality + ": " + this.policy;
            }
        }
    }

    let ernie = new StoreItemss("Tadjiev", "Uzbek", "strict");
    let vera = new StoreItemss("Sanjar", "Russian", "relaxed");

I found a new method through class to create objects. Is it a better way? And, global variables to store those instantiated objects would be a better idea maybe? But still I don't understand how to return all the values of one object by accessing to its variable? Let's say if Complications selected, I present only 3 Objects which are the watches.

Steven Parker
Steven Parker
231,153 Points

The class/constructor syntax is newer but the objects created are the same.

And yes, making the variables global would allow them to be accessed from the other function. But that's only half the issue, as they were being assigned numbers but being accessed as if they were objects.

Tadjiev Codes
Tadjiev Codes
9,626 Points
function displayStoreItems() {

        // clears the output every time
        outputElement.innerHTML = "";


        var displayFilter = document.querySelector("select>option[name='filter']");
        console.log("Current Filter: " + displayFilter);


        //Loop through array
        for (var i = 0; i < StoreItems.length; i++) {

            //var tempEL = document.createElement("p");
            var tempStoreItem = StoreItems[i]; //Instead of typing StoreItems[i] every time the array we need, we can assign to a variable and use that to refer
            //to the properties in our object instead
            //The above method is easier as there's like kinda less code



            /* //Display based on filter
             if ((tempStoreItem.Category == true && displayFilter == "Complications") ||
                 (tempStoreItem.Category == false && displayFilter == "Classic") ||
                 displayFilter == "All") {
              */
            if (departmentSelection.value === 'Complications' && tempStoreItem.Category == 'Complications') {

                var tempEL = document.createElement("p");
                tempEL.innerText = tempStoreItem.Id + "" + tempStoreItem.Name + "" + tempStoreItem.Price + "" + tempStoreItem.Quantity + "" +
                    tempStoreItem.MaxPerCustomer + "" + tempStoreItem.Category + "" + tempStoreItem.Image + "";
                //so because ernie is in global variable outside we can access it here

                //This libe gives it a color
                tempEL.style.border = "1px solid " + '#55AB55';


                //Append to the Div
                outputElement.appendChild(tempEL);


            } // end if
            else if (departmentSelection.value === 'Classic' && tempStoreItem.Category == 'Classic') {

                var tempEL = document.createElement("p");

                tempEL.innerText = tempStoreItem.Id + "" + tempStoreItem.Name + "" + tempStoreItem.Price + "" + tempStoreItem.Quantity + "" +
                    tempStoreItem.MaxPerCustomer + "" + tempStoreItem.Category + "" + tempStoreItem.Image + "";
                //so because ernie is in global variable outside we can access it here

                //This libe gives it a color
                tempEL.style.border = "1px solid " + '#55AB55';


                //Append to the Div
                outputElement.appendChild(tempEL);


            } //end if
            else if (departmentSelection.value === 'All') {

                var tempEL = document.createElement("p");

                tempEL.innerText = tempStoreItem.Id + "" + tempStoreItem.Name + "" + tempStoreItem.Price + "" + tempStoreItem.Quantity + "" +
                    tempStoreItem.MaxPerCustomer + "" + tempStoreItem.Category + "" + tempStoreItem.Image + "";
                //so because ernie is in global variable outside we can access it here

                //This libe gives it a color
                tempEL.style.border = "1px solid " + '#55AB55';


                //Append to the Div
                outputElement.appendChild(tempEL);


            }


        } //end for loop

    } //end function

Now actually it displays by order of the Category if All and if Complications Category or the Classic Category. What is the best way to add the images into objects? I tried doing 'endvr2.png' // adding filenames as strings in order to add the required images but it didn't really work.OR it's better to add that through HTML and create Cards as divs? Thanks

Steven Parker
Steven Parker
231,153 Points

I'm wondering if we're using the same terms here. You wouldn't normally have images in objects. You might have references to images in objects. Or you might add images to a web page (the DOM). I'm not sure what you're attempting.

And what's with all the concatenation of empty strings? ( + "" + ). I don't think that does anything.

For any future issues, it would probably be better to start a brand new question. And to make it possible to easily replicate any issues, make a snapshot of your workspace and post the link to it with the question (then you won't need to paste in code).

Tadjiev Codes
Tadjiev Codes
9,626 Points

Hi Dear Mr.Steven , Yes I understand that we just reference the images but how better to reference them. And yes Our professor used to keep this empty string but logically if no space in them they don't even separate the message. So I'll use space within it or "|" to separate the words. Sure yeah, I'll post this and other questions as a new link to make it clearer. Thanks a lot)))