TypeError undefined when trying to get cookie object thru arrayList

I am making a page that sorts values in an array by name, and then when I click on a button "write to cookie" it should store it, then I click on sort by age and then click on a button "read from cookie" the new output should be the list that I stored when I clicked on "write to cookie" previously.

I keep getting an error when I click on "read from cookie": enter image description here

index.html :

<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>
            body {
                font-family: tahoma, sans-serif;
                padding: 1em;
            }
            div {
                padding: 1em;
            }

            h3 {
                margin-bottom: -0.5em;
            }

        </style>
    </head>
    <body>
        <input type="button" onclick ="sortByAge()" value="Age Sort"/>
        <input type="button" onclick ="sortByName()" value="Name Sort"/>
        <input type="button" onclick="writePerson()" value="Write List to Cookie" />
        <input type="button" onclick="readPerson()" value="Read List from Cookie" />

        <h3>Person List</h3>
        <div id="contacts"></div>

        <script src="sort.js"></script>
        <script src="CookiesWithObjects.js"></script>
        <script>

            // If you do not use this and you misspell a variable name, one is auto-declared. 
            "use strict";

            //debugger;

            function refreshPersonList() {
                var output = "";
                for (var i = 0; i < personList.length; i++) {
                    output += personList[i].getName() + " " + personList[i].getAge() + "<br/>";
                }
                document.getElementById("contacts").innerHTML = output + "<br/>";
            }

            function sortByName() {
                console.log("to sort by name");
                sortByKey(personList, "getName()");
                refreshPersonList();
            }

            function sortByAge() {
                console.log("to sort by age");
                sortByKey(personList, "getAge()");
                refreshPersonList();
            }

            function writePerson() {
                Cookie.setCookieObj("myPerson", personList, 365);
            }

            function readPerson() {
                personList = Cookie.getCookieObj("myPerson");
                refreshPersonList();
            }

            function MakePerson(newName, newAge) {
                var person = {};
                var name = newName;
                var age = newAge;
                person.getAge = function () {
                    return age;
                };
                person.getName = function () {
                    return name;
                };
                return person;
            }


            // main program 
            var personList = []; // empty array
            personList[0] = MakePerson("sally", 20);
            personList[1] = MakePerson("abe", 40);
            personList[2] = MakePerson("dave", 35);
            personList[3] = MakePerson("frank", 55);
            personList[4] = MakePerson("ellie", 15);
            personList[5] = MakePerson("debbie", 60);

            refreshPersonList();

        </script>

    </body>
</html>

CookieWithObjects.js :

var Cookie = {};

Cookie.setCookie = function (cname, cvalue, exdays) {
    if (!exdays) {
        exdays = 365;
    }
    var d = new Date();
    d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
    var expires = "expires=" + d.toUTCString();
    document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
    console.log("cookie stored");
};

Cookie.setCookieObj = function (cname, cObj, exdays) {
    var jsonString = JSON.stringify(cObj);
    Cookie.setCookie(cname, jsonString, exdays);
};

Cookie.getCookie = function (cname) {
    var name = cname + "=";
    var decodedCookie = decodeURIComponent(document.cookie);
    var ca = decodedCookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) === ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) === 0) {
            return c.substring(name.length, c.length);
        }
    }
    console.log("cookie read");
    return "";
};

Cookie.getCookieObj = function (cname) {
    var jsonString = Cookie.getCookie(cname);
    if (!jsonString) {
        return null;
    }
    jsonString = "(" + jsonString + ")";
    var obj = eval(jsonString);
    return obj;
};

2 answers

  • answered 2018-02-13 01:02 Harun Diluka Heshan

    Instead of eval() try using JSON.parse() because eval() doesn't return the object. It just evaluates it.

    Cookie.getCookieObj = function (cname) {
        var jsonString = Cookie.getCookie(cname);
        if (!jsonString) {
            return null;
        }
        var obj = JSON.parse(jsonString);
        return obj;
    };
    

    And most importantly change your constructor's getAge(), getName() methods to properties.

            function MakePerson(newName, newAge) {
                var person = {};
                person.getAge = newAge;
                person.getName = newName;
                return person;
            }
    

  • answered 2018-02-13 02:21 Medet Tleukabiluly

    You have 2 problems

    Problem 1

    Your MakePerson is a class, and the instance doesn't have properties
    So when storing Cookie.setCookieObj("myPerson", personList, 365)
    It actually stores

    myPerson [{},{},{},{},{},{}]    
    

    You need to persist properties

    function MakePerson(newName, newAge) {
        var person = {};
        person.name = newName;
        person.age = newAge;
        return person;
    }
    

    Problem 2

    You return null in Cookie.getCookieObj
    But you are not checking the value in refreshPersonList function

    function refreshPersonList() {
        var output = "";
        if (personList && personList.length) { // <== added check
            for (var i = 0; i < personList.length; i++) {
                // change getName()/getAge() to name/age
                output += personList[i].name + " " + personList[i].age + "<br/>";
            }
            document.getElementById("contacts").innerHTML = output + "<br/>";
        }
    }
    

    Problem 3

    Also Harun Diluka Heshan made good point, you must JSON.parse, not eval