John Coolidge
John Coolidge

Reputation: 155

cannot set property title of undefined

I have an object literal which contains functions. I'm getting an error "cannot set property title of undefined". In the editBook function below, I want to store the pElement's inner text as the object's title property (look for comment: "//store p's edited value as the title key in object").

//store p's edited value as the title key in object
  var object = library.books[index];
  object.title = pElement.innerText;

I tried using a 0 in place of the index function and when I added a book and edited it, everything went well. When I put in my function, it doesn't say there was an issue with the function, but that it couldn't set the property of undefined. I don't know if there is a problem with my indexing function, or if there is something else going on.

var addButton = document.querySelector("#add");
var searchButton = document.querySelector("#search");
var titleInput = document.querySelector("#title");
var display = document.querySelector("#display");


function Book(title) {
    this.title = title;
}

function Library() {
    this.books = [];
}

Library.prototype.add = function(book) {
        this.books.push(book);
}

//btw library.books is an array of objects
var library = new Library();

//Library UI
var libraryUI = {
    //Add a new book
    addBook: function() {
        display.innerHTML = "";
        var newBook = libraryUI.createNewBook(titleInput.value);
        library.add(newBook);
        //log the books for console reasons
        console.log(library.books);
        titleInput.value = "";
    },
    //Create a new book
    createNewBook: function(title) {
        var book = new Book(title);
        return book;
    },
    //Search for a book
    searchBook: function() {
        display.innerHTML = "";
        var search = titleInput.value;
        for (var i = 0; i < library.books.length; i++) {
            var book = library.books[i];
            if (book.title === search) {
                var bookResult = book.title;

                //create editButton, deleteButton and p element
                var editButton = document.createElement("button");
                var deleteButton = document.createElement("button");
                var pElement = document.createElement("p");

                //modify elements
                editButton.innerText = "Edit";
                deleteButton.innerText = "Delete";
                editButton.className = "edit";
                deleteButton.className = "delete";

                pElement.className = "displayResult";
                pElement.innerHTML = bookResult;

                //display result and append buttons
                display.appendChild(pElement);
                display.appendChild(editButton);
                display.appendChild(deleteButton);

                //bind events to new buttons
                libraryUI.bindEvents();
            }
        }
    },
    //delete a book
    deleteBook: function() {
        //Access the book's index value in the array

            //Remove the book from the array

    },
    //edit a book
    editBook: function() {
        var pElement = document.querySelector(".displayResult"); //p element
        var displayDiv = document.querySelector("#display"); //div element
        var editButton = document.querySelector(".edit");
        var containsClass = pElement.classList.contains("editMode");
        var index = libraryUI.findIndex(library.books, pElement);

        //If class of p is editMode
        if (containsClass) {
            var input = document.querySelector(".inputEl");

            //switch from editMode (remove class)
            pElement.classList.toggle("editMode");

            //p's value becomes the label's text
            pElement.innerText = input.value;

            //remove input element
            display.removeChild(input);

            //switch "Save" to "Edit"
            editButton.innerText = "Edit";

            //store p's edited value as the title key in object
            var object = library.books[index];
            object.title = pElement.innerText;

        } else {
            //switch to editMode
            pElement.classList.toggle("editMode");

            //create input element
            var inputEl = document.createElement("input");

            //modify elements
            inputEl.type = "text";
            inputEl.className = "inputEl";

            //append input element
            display.insertBefore(inputEl, display.childNodes[0]);

            //input value becomes p's text
            inputEl.value = pElement.innerText;

            //switch "Edit" to "Save"
            editButton.innerText = "Save";
        }   
    },
    //bind events
    bindEvents: function() {
        var editButton = document.querySelector(".edit");
        var deleteButton = document.querySelector(".delete");

        editButton.onclick = libraryUI.editBook;
        deleteButton.onclick = libraryUI.deleteBook;
    },
    //find the index of a book in library
    findIndex: function(array, title) {
        for (var i = 0; i < array.length; i++) {
            if (array[i].title == title)
                return i;
        }
        return -1;
    }

};

addButton.addEventListener("click", libraryUI.addBook);
searchButton.addEventListener("click", libraryUI.searchBook);

The HTML:

<!DOCTYPE html>
<html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>Library App</title>
        <link rel="stylesheet" type="text/css" href="css/style.css">
    </head>
    <body>

        <h1>Personal Library</h1>

        <label for="title">Title: </label>
        <input type="text" id="title">

        <button id="add">Add</button>
        <button id="search">Search</button>

        <div id="display">

        </div>

        <script src="js/app.js"></script>
    </body>
</html>

Upvotes: 1

Views: 1518

Answers (1)

Amber
Amber

Reputation: 2463

In editBook you are searching on the ".displayResult" paragraph element rather than the text inside the paragraph so libraryUI.findIndex doesn't find the matching element and returns -1 (which is why you're attempting to set the title of 'undefined').

This line:

var index = libraryUI.findIndex(library.books, pElement);

should be:

var index = libraryUI.findIndex(library.books, pElement.innerText);

Upvotes: 1

Related Questions