Now that we know how to loop through an object's keys (properties), let's update our user interface code so we can display all of the Contact
s on our site.
Contact
DataWe'll start by writing an empty displayContactDetails()
method below our global variable but above our form submission code:
...
// User Interface Logic ---------
let addressBook = new AddressBook();
function displayContactDetails(addressBookToDisplay) {
}
$(document).ready(function() {
$("form#new-contact").submit(function(event) {
event.preventDefault();
const inputtedFirstName = $("input#new-first-name").val();
const inputtedLastName = $("input#new-last-name").val();
const inputtedPhoneNumber = $("input#new-phone-number").val();
let newContact = new Contact(inputtedFirstName, inputtedLastName, inputtedPhoneNumber);
addressBook.addContact(newContact);
console.log(addressBook.contacts);
});
});
As the function name states, this method will display the details of contacts. It will takes an AddressBook
object as an argument. Also, notice we're not putting it directly into the block of code with our form submission listener. This is a best practice. By separating our code out, it's cleaner, easier to read, and easier to debug and refactor.
Now let's actually write the code that goes in this method. We'll apply new best practices along the way too:
...
function displayContactDetails(addressBookToDisplay) {
let contactsList = $("ul#contacts");
let htmlForContactInfo = "";
Object.keys(addressBookToDisplay.contacts).forEach(function(key) {
const contact = addressBookToDisplay.findContact(key);
htmlForContactInfo += "<li id=" + contact.id + ">" + contact.firstName + " " + contact.lastName + "</li>";
});
contactsList.html(htmlForContactInfo);
}
...
First we save our jQuery ul#contacts
element in a variable called contactsList
. This is a best practice because it takes jQuery time to query the DOM and find ul#contacts
. Saving it in a variable prevents our application from needing to check the DOM again if we need to use the selector multiple times. This is much more efficient. In general, we want to query the DOM as little as possible. Querying the DOM once and saving values in a variable is always going to be better than querying the DOM multiple times.
Next, we create a string called htmlForContactInfo
. The purpose of this variable is to construct all the HTML for our contact list before querying the DOM. We'll discuss this further in a moment.
Then we use Object.keys()
to get all the keys from addressBookToDisplay.contacts
so we can iterate through them.
In our loop, we grab each contact
by using our AddressBook.prototype.find()
method.
Finally, we construct our HTML as a string and append it to htmlForContactInfo
. You might wonder why we are going to the trouble to construct this string instead of just appending each contact to the DOM one at a time. However, as we just discussed, querying the DOM takes time. It is actually quite a slow process as far as coding is involved - much slower than most other code we'll write. Let's say, for instance, that our address book has one hundred contacts. By constructing our HTML string all at once, we only have to query the DOM once instead of one hundred times. This is much, much more efficient.
Let's take a look at what's actually getting appended to the HTML string with each contact:
"<li id=" + contact.id + ">" + contact.firstName + " " + contact.lastName + "</li>"
Each contact is being attached to an <li>
with a dynamic id
matching the Contact
's id
property. This is very important. We can later retrieve this id
stored in the <li>
to use with our AddressBook.prototype.findContact()
method to locate an entire Contact
object. If we didn't attach this information to the HTML string, our application would have no way to easily get the ID.
Let's call this new displayContactDetails
function whenever we add a new Contact
. All we have to do is remove our console.log()
and replace it with this new function.
...
$(document).ready(function() {
$("form#new-contact").submit(function(event) {
event.preventDefault();
const inputtedFirstName = $("input#new-first-name").val();
const inputtedLastName = $("input#new-last-name").val();
const inputtedPhoneNumber = $("input#new-phone-number").val();
let newContact = new Contact(inputtedFirstName, inputtedLastName, inputtedPhoneNumber);
addressBook.addContact(newContact);
displayContactDetails(addressBook); // <--- This is the new line!
});
});
Now each time we add a new Contact
, the page will update and add the contact's first and last names to the list of contacts. Try it out for yourself in the browser.
If we open Chrome Developer Tools and inspect elements on the page (right-click and then select Inspect) we'll see each Contact
's <li>
entry has a unique id
corresponding to the Contact
object's automatically-assigned id
property. The GIF below demonstrates this:
While this dynamic ID isn't doing anything yet, we'll soon be adding functionality so that we can click on a contact and get additional information based on its ID.
After following along, our updated scripts.js
file looks like this:
// Business Logic for AddressBook ---------
function AddressBook() {
this.contacts = {};
this.currentId = 0;
}
AddressBook.prototype.addContact = function(contact) {
contact.id = this.assignId();
this.contacts[contact.id] = contact;
};
AddressBook.prototype.assignId = function() {
this.currentId += 1;
return this.currentId;
};
AddressBook.prototype.findContact = function(id) {
if (this.contacts[id] != undefined) {
return this.contacts[id];
}
return false;
};
AddressBook.prototype.deleteContact = function(id) {
if (this.contacts[id] === undefined) {
return false;
}
delete this.contacts[id];
return true;
};
// Business Logic for Contacts ---------
function Contact(firstName, lastName, phoneNumber) {
this.firstName = firstName;
this.lastName = lastName;
this.phoneNumber = phoneNumber;
}
Contact.prototype.fullName = function() {
return this.firstName + " " + this.lastName;
};
// User Interface Logic ---------
let addressBook = new AddressBook();
function displayContactDetails(addressBookToDisplay) {
let contactsList = $("ul#contacts");
let htmlForContactInfo = "";
Object.keys(addressBookToDisplay.contacts).forEach(function(key) {
const contact = addressBookToDisplay.findContact(key);
htmlForContactInfo += "<li id=" + contact.id + ">" + contact.firstName + " " + contact.lastName + "</li>";
});
contactsList.html(htmlForContactInfo);
}
$(document).ready(function() {
$("form#new-contact").submit(function(event) {
event.preventDefault();
const inputtedFirstName = $("input#new-first-name").val();
const inputtedLastName = $("input#new-last-name").val();
const inputtedPhoneNumber = $("input#new-phone-number").val();
let newContact = new Contact(inputtedFirstName, inputtedLastName, inputtedPhoneNumber);
addressBook.addContact(newContact);
displayContactDetails(addressBook);
});
});
Let's recap some of the best practices we just used:
We created a separate UI function instead of adding the code to our form submission block. This allows us to focus on writing one function at a time, and helps keep code modular.
We store a jQuery selector inside a variable. That way, if we need to use the selector multiple times, jQuery only needs to query the DOM once, making code faster and more efficient.
We create a list of all elements we want to append to the DOM, and add them all at once instead of one a time. This is also faster and more efficient.
You aren't expected to master these best practices just yet, but continually practice integrating them in your code throughout the course. These kinds of details separate beginning coders from more experienced ones.
In addition to these best practices, we also applied our new knowledge of looping through object keys.
In the next lesson, we'll add UI functions that will allow us to display the detailed information of an individual contact onscreen.
Create a separate UI function instead of adding the code to the form submission block. This allows us to focus on writing one function at a time, and helps keep code modular.
Store jQuery selectors inside a variable. That way, if we need to use the selector multiple times, jQuery only needs to query the DOM once, making code faster and more efficient.
Create a list of all elements to append to the DOM, and add them all at once instead of one a time. This is also faster and more efficient.
Create a UI function to display contacts in an address book:
function displayContactDetails(addressBookToDisplay) {
let contactsList = $("ul#contacts");
let htmlForContactInfo = "";
Object.keys(addressBookToDisplay.contacts).forEach(function(key) {
const contact = addressBookToDisplay.findContact(key);
htmlForContactInfo += "<li id=" + contact.id + ">" + contact.firstName + " " + contact.lastName + "</li>";
});
contactsList.html(htmlForContactInfo);
}
Lesson 18 of 32
Last updated April 8, 2021