2

I have created a number of instances of a object constructor which I have placed into an array and looped over to display into a list. Now I want to select a name property from that list to use in an onclick event handler (not shown in this code). I would like to know how to access the name property in the click handler. This is what i have tried so far but i keep getting undefined.

console.log(contactarray[i].name);
console.log(contactarray.name);

code

$(document).ready(function() {

function ContactList (name, email, number,address) {
    this.name = name;
    this.email = email;
    this.number = number;
    this.address = '6539 Wilton Ave Culver City CA 90234';
}

var christian = new ContactList('Christian', 'christian@example.com', '323-555-124');
var rich = new ContactList('Rich', 'rich@example.com', '323-555-124');
var scott = new ContactList('Scott', 'scott@example.com', '323-555-124');
var danny = new ContactList('Danny', 'danny@example.com', '323-555-124');
var taka = new ContactList('Taka', 'taka@example.com', '323-555-124');
var tim = new ContactList('Tim', 'tim@example.com', '323-555-124');
var patrick = new ContactList('Patrick', 'patrick@example.com', '323-555-124');
var jacques = new ContactList('Jacques', 'jacques@example.com', '323-555-124');

var contactarray = [christian, rich, scott, danny, taka, tim, patrick, jacques];

for (i = 0; i < contactarray.length; i++) {
    $('#contacts').append('<li class="itemname" id="'+i+'"><a href="#">' + contactarray[i].name + '</a></li>');
}

My issue is getting access to the name property of one of the list items when it is clicked.

Michael Geary
  • 28,450
  • 9
  • 65
  • 75
Sai
  • 801
  • 3
  • 10
  • 27

3 Answers3

3

What you've run into is the classic problem with asynchronous JavaScript events in a loop. This was not apparent from your question because it didn't have a click handler anywhere, but it became obvious from your subsequent comment. Always provide enough information in a question to reproduce the actual problem. Simplified code is good, but not when the essential problem area is simplified out!

The easiest solution is to call a function for each loop iteration. Each time you call a function, it creates a "closure" which captures all the parameters and local variables in that function, even for asynchronous code like a click handler which gets called later.

Since you're using jQuery, you can do that with $.each(), or you could create and call a function of your own in a for loop, as long as you call it for every loop iteration.

Here's a working solution. I also simplified your code a bit by putting the contact items directly inside the array instead of creating a named variable for each one. And I changed the name of your ContactList constructor to ContactItem because it represents an individual item and not a list:

function ContactItem( name, email, number,address ) {
    this.name = name;
    this.email = email;
    this.number = number;
    this.address = '6539 Wilton Ave Culver City CA 90234';
}

var contactarray = [
    new ContactItem('Christian', 'christian@example.com', '323-555-124'),
    new ContactItem('Rich', 'rich@example.com', '323-555-124'),
    new ContactItem('Scott', 'scott@example.com', '323-555-124'),
    new ContactItem('Danny', 'danny@example.com', '323-555-124'),
    new ContactItem('Taka', 'taka@example.com', '323-555-124'),
    new ContactItem('Tim', 'tim@example.com', '323-555-124'),
    new ContactItem('Patrick', 'patrick@example.com', '323-555-124'),
    new ContactItem('Jacques', 'jacques@example.com', '323-555-124')
];

var $contacts = $('#contacts');

$.each( contactarray, function( i, contact ) {
    var $contact = $(
        '<li class="itemname" id="' + i + '">' +
            '<a href="#">' + contact.name + '</a>' +
        '</li>'
    );
    $contact.click( function() {
        alert( contact.name );
    }).appendTo( $contacts );
});

Updated fiddle

Michael Geary
  • 28,450
  • 9
  • 65
  • 75
  • I am still a bit new to jQuery so i tried to call a function in a for loop but then my other function doesn't display, here is a link to a fiddle with my full code http://jsfiddle.net/eyk10fpe/1/ my main objective is to click on a name and display that names email, number and address next to it. Why is it when i put my 1st for loop in a function and call it, both functions disappear? sorry for the hassle – Sai Jul 19 '15 at 08:12
  • I fixed the functions disappearing, i tried to edit but ran out of time. in your opinion what would be the best way to implement what i sugested? – Sai Jul 19 '15 at 08:23
  • I'm not sure if I quite understand the latest question. But I notice that your latest code is back to using `for` loops instead of `$.each()`, and also it doesn't have any `click` handlers at all. I suggest comparing with the code I posted in my answer that has both of those things. If you do it the way that code does and add your new features to that, it should work. – Michael Geary Jul 19 '15 at 08:47
  • Also, let's use `@example.com` for all the email addresses, instead of addresses that might actually belong to real people. I edited your question and both answers to use `@example.com` addresses. When you make the next revision to your fiddle could you make the same change? – Michael Geary Jul 19 '15 at 08:57
  • thanks for getting back to me, the emails are fake to begin with so no worries there. I don't fully understand what you did, this is still new to me so that's why I didn't use it, here is a updated fiddle, http://jsfiddle.net/eyk10fpe/3/ I have commented my intentions for the code. so in the end for example if I click on scott it should display his email, number and address, same for anyone else. is there a way to implement this? – Sai Jul 19 '15 at 11:53
-1

Try replace

for (i = 0; i < contactarray.length; i++) {
    $('#contacts').append('<li class="itemname" id="'+i+'"><a href="#">' + contactarray[i].name + '</a></li>');
}

to

contactarray.forEach(function(contact, id) {
    $('#contacts').append('<li class="itemname" id="'+id+'"><a href="#" onclick="alert(' + contact.name + ')">' + contact.name + '</a></li>');
});
monkey
  • 1,279
  • 14
  • 15
-1
function ContactList (name, email, number,address) {
    this.name = name;
    this.email = email;
    this.number = number;
   this.address = '6539 Wilton Ave Culver City CA 90234';
}

window.onload = function() 
{
     var christian = new ContactList('Christian', 'christian@example.com','');
     var rich = new ContactList('Rich', 'rich@example.com', '323-555-124');
     var scott = new ContactList('Scott', 'scott@example.com', '323-555-');
     var contactarray = [christian, rich, scott];

     var btn = document.getElementById('btn');  

     btn.addEventListener('click',function(){
          for (i = 0; i < contactarray.length; i++) {
         $('#contacts').append('<li class="itemname" id="'+i+'"><a  href="#">' + contactarray[i].name + '</a></li>');
      }
     },false);

}
Michael Geary
  • 28,450
  • 9
  • 65
  • 75