-1

I am developing a web application in this case a front-end where I need to display Facebook events. I define an array called events. Inside each new event I have:

  • id : id of the event.
  • name : name of the event.
  • description : description of the event.
  • start_date : the start date of the event.
  • end_date : the end date of the event.
  • participants : array with participants in the event
  • pictures : array of pictures of the event.
  • places : array of places in the event.
var events = [];

var new_event = {
    'id': event_id,
    'name': event_name,
    'description': event_description,
    'start_date': event_start_date,
    'end_date': event_end_date,
    'participants' : [],
    'pictures' : [],
    'places' : []
};

then i create several participants, pictures and places.

var new_participant = {
    'id': participant_id,
    'name': participant_name,
    'birthDate': participant_birth_date,
    'pictureUrl': participant_photo_url
};

Every new participant has the variables on top.

and i make the following pushes:

events.push(new_event);
events[i].participants.push(new_participant);

i goes from 0 to events.length - 1.

but I get the following error in the browser:

Uncaught TypeError: Cannot read property 'participants' of undefined

What is the correct way of pushing arrays into javascript elements and how do I access them?

When I try to access:

events[i].participants[0].name

where i is between 0 and events.length-1, I get the same error for the name property.

Uncaught TypeError: Cannot read property 'name' of undefined

Here is the full code:

$(document)
    .ready(
        function() {

            var events = [];

            $.ajax({
                type : "GET",
                url : "...",
                dataType : "xml",

                success : function(xml) {


                    $(xml).find('events').each(function() {

                        var event_id = $(this).find('id').text();
                        var event_name = $(this).find('name').text();
                        var event_description = $(this).find('description').text();
                        var event_start_date = $(this).find('startdate').text();
                        var event_end_date = $(this).find('enddate').text();

                        var new_event = {
                            'id': event_id,
                            'name': event_name,
                            'description': event_description,
                            'start_date': event_start_date,
                            'end_date': event_end_date,
                            'participants' : [],
                            'pictures' : [],
                            'places' : []
                        };

                        events.push(new_event);

                    });

                    for(var i=0; i < events.length; i++){
                        $.ajax({
                            type : "GET",
                            url : "...",
                            dataType : "xml",

                            success : function(xml) {

                                $(xml).find('user').each(function() {

                                    var participant_id = $(this).find('id').text();
                                    var participant_name = $(this).find('name').text();
                                    var participant_birth_date = $(this).find('birthDate').text();
                                    var participant_photo_url = $(this).find('pictureUrl').text();

                                    if(participant_name !== ""){
                                        var new_participant = {
                                                'id': participant_id,
                                                'name': participant_name,
                                                'birthDate': participant_birth_date,
                                                'pictureUrl': participant_photo_url
                                            };
                                        events[i].participants.push(new_participant);
                                    }


                                });

                            },
                            error : function(xhr) {
                                alert(xhr.responseText);
                            }
                        });

                        $.ajax({
                            type : "GET",
                            url : "...",
                            dataType : "xml",

                            success : function(xml) {



                                $(xml).find('place').each(function() {

                                    var place_id = $(this).find('id').text();
                                    var place_name = $(this).find('name').text();

                                    if(place_name !== ""){
                                        var new_place = {
                                                'id': place_id,
                                                'name': place_name,
                                            };
                                        events[i].places.push(new_place);
                                        alert("novo local: "+new_place.name);
                                    }
                                });



                            },
                            error : function(xhr) {
                                alert(xhr.responseText);
                            }
                        });

                        $.ajax({
                            type : "GET",
                            url : "...",
                            dataType : "xml",

                            success : function(xml) {



                                $(xml).find('media').each(function() {

                                    var media_id = $(this).find('id').text();
                                    var media_url = $(this).find('url').text();
                                    var media_content = $(this).find('content').text();

                                    if(media_url !== ""){
                                        var new_media = {
                                                'id': media_id,
                                                'url': media_url,
                                                'content' : media_content
                                            };
                                        events[i].pictures.push(new_media);
                                        alert("novo media: "+new_media.url);
                                    }
                                });

                            },
                            error : function(xhr) {
                                alert(xhr.responseText);
                            }
                        });
                    }

                    var result_html = '';
                    var index = 0;

                    result_html += '<div class="f-page f-cover"><div class="cover-elements"><div class="f-cover-story"><span>Life Events</span>Photo Album</div></div><div class="f-cover-flip">&lt; swipe</div></div>';

                    for(var i = events.length; i > 0 ; i -= 5 ){
                        result_html += '<div class="f-page">';
                            result_html += '<div class="f-title">';
                                result_html += '<a href="index.jsp">Back to bookshelf</a>';
                                result_html += '<h2 id="event_name">Your Life Events</h2>';
                                result_html += '<a href="#"></a>';
                            result_html += '</div>';

                            if(index < events.length){
                                $('.img-1').css({'background-image: ': 'url('+events[index].pictures[0].url+')'});
                                result_html += '<div class="box w-25 h-70" id="top_left_box"><div class="img-cont img-1"></div><h3>'
                                            + events[index].name + '<span>Published ' + 'From: ' + events[index].start_date + 'to: ' + events[index].end_date + '</span></h3><p>'
                                            + events[index].description + ' With: ' + events[index].participants[0].name + events[index].participants[0].pictureUrl + '</p></div>';
                                index++;
                            }
                            if(index < events.length){
                                $('.img-2').css({'background-image: ': 'url('+events[index].pictures[0].url+')', 'height: ': '60%'});
                                result_html += '<div class="box w-50 h-70 box-b-l box-b-r" id="top_center_box"><div class="img-cont img-2"></div><h3>'
                                            + events[index].name + '<span>Published ' + 'From: ' + events[index].start_date + 'to: ' + events[index].end_date + '</span></h3><p>'
                                            + events[index].description + ' With: ' + events[index].participants[0].name + events[index].participants[0].pictureUrl + '</p></div>';
                                index++;
                            }   
                            if(index < events.length){
                                $(".img-3").css({'background-image: ': 'url('+events[index].pictures[0].url+')'});
                                result_html += '<div class="box w-25 h-70" id="top_right_box"><div class="img-cont img-3"></div><h3>'
                                            + events[index].name + '<span>Published ' + 'From: ' + events[index].start_date + 'to: ' + events[index].end_date + '</span></h3><p>'
                                            + events[index].description + ' With: ' + events[index].participants[0].name + events[index].participants[0].pictureUrl + '</p></div>';
                                index++;
                            }
                            if(index < events.length){
                                result_html += '<div class="box w-50 h-30 box-b-r title-top" id="bottom_left_box"><h3>'
                                            + events[index].name + '<span>Published ' + 'From: ' + events[index].start_date + 'to: ' + events[index].end_date + '</span></h3><p>'
                                            + events[index].description + ' With: ' + events[index].participants[0].name + events[index].participants[0].pictureUrl + '</p></div>';
                                index++;
                            }
                            if(index < events.length){
                                result_html += '<div class="box w-50 h-30 title-top" id="bottom_right_box"><h3>' 
                                            + events[index].name + '<span>Published ' + 'From: ' + events[index].start_date + 'to: ' + events[index].end_date + '</span></h3><p>'
                                            + events[index].description + ' With: ' + events[index].participants[0].name + events[index].participants[0].pictureUrl + '</p></div>';
                                index++;
                            }
                        result_html += '</div>';

                    }

                    result_html += '<div class="f-page f-cover-back"><div id="codrops-ad-wrapper"><a href="index.jsp" >Back to bookshelf</a></div></div>';
                    $('#flip').html(result_html);

                },

                error : function(xhr) {
                    alert(xhr.responseText
                            + " Error retrieving data from server");
                }


            });



    });

After following suggestion here is what i got to:

$(document)
    .ready(
        function() {

            var events = [];

            $.ajax({
                type : "GET",
                url : "",
                dataType : "xml",

                success : function(xml) {


                    $(xml).find('events').each(function() {

                        var event_id = $(this).find('id').text();
                        var event_name = $(this).find('name').text();
                        var event_description = $(this).find('description').text();
                        var event_start_date = $(this).find('startdate').text();
                        var event_end_date = $(this).find('enddate').text();

                        var new_event = {
                            'id': event_id,
                            'name': event_name,
                            'description': event_description,
                            'start_date': event_start_date,
                            'end_date': event_end_date,
                            'participants' : [],
                            'pictures' : [],
                            'places' : []
                        };

                        events.push(new_event);

                    });


events.forEach(function(event){
                        $.ajax({
                            type : "GET",
                            url : "..."+ event.id + "...",
                            dataType : "xml",

                            success : function(xml) {

                                $(xml).find('user').each(function() {

                                    var participant_id = $(this).find('id').text();
                                    var participant_name = $(this).find('name').text();
                                    var participant_birth_date = $(this).find('birthDate').text();
                                    var participant_photo_url = $(this).find('pictureUrl').text();

                                    if(participant_name !== ""){
                                        var new_participant = {
                                                'id': participant_id,
                                                'name': participant_name,
                                                'birthDate': participant_birth_date,
                                                'pictureUrl': participant_photo_url
                                            };
                                        event.participants.push(new_participant);
                                    }


                                });

                            },
                            error : function(xhr) {
                                alert(xhr.responseText);
                            }
                        });

                        $.ajax({
                            type : "GET",
                            url : "..."+ event.id + "...",
                            dataType : "xml",

                            success : function(xml) {



                                $(xml).find('place').each(function() {

                                    var place_id = $(this).find('id').text();
                                    var place_name = $(this).find('name').text();

                                    if(place_name !== ""){
                                        var new_place = {
                                                'id': place_id,
                                                'name': place_name,
                                            };
                                        event.places.push(new_place);
                                    }
                                });



                            },
                            error : function(xhr) {
                                alert(xhr.responseText);
                            }
                        });

                        $.ajax({
                            type : "GET",
                            url : "..."+ event.id + "...",
                            dataType : "xml",

                            success : function(xml) {

                                $(xml).find('media').each(function() {

                                    var media_id = $(this).find('id').text();
                                    var media_url = $(this).find('url').text();
                                    var media_content = $(this).find('content').text();

                                    if(media_url !== ""){
                                        var new_media = {
                                                'id': media_id,
                                                'url': media_url,
                                                'content' : media_content
                                            };
                                        event.pictures.push(new_media);
                                    }
                                });

                            },
                            error : function(xhr) {
                                alert(xhr.responseText);
                            }
                        });
                        alert(event.participants[0].name);
                        alert(event.pictures[0].url);
                        alert(event.places[0].name);
                    });

Still having the same error in name :

Uncaught TypeError: Cannot read property 'name' of undefined 
João
  • 331
  • 1
  • 3
  • 17
  • 1
    What is the value of `i` at the time you are attempting to access `events[i]`? – ಠ_ಠ Jul 15 '14 at 15:37
  • it can be from 0 to events.length . – João Jul 15 '14 at 15:37
  • 1
    Please create a [Minimal, Complete and Verifiable Example](http://stackoverflow.com/help/mcve) that we can take a look at and try. We cannot know what is going on in your code. – kapa Jul 15 '14 at 15:37
  • @João: Basically, `i` is outside of the bounds of the array. Also, you need `participants.push(new_participant);` rather than `participants[0].push(new_participant);`. – Matt Jul 15 '14 at 15:38
  • 2
    @João You mean `events.length - 1`? ;) – kapa Jul 15 '14 at 15:38
  • the message says that events[i] is undefined, means the variable doesn't exists. It doesn't mean that you've made a mistake in the syntaxe. – TCHdvlp Jul 15 '14 at 15:38
  • events[i] exists the problem is the participants variable. Yes i mean lenght-1 @kapa. – João Jul 15 '14 at 15:40
  • @João The error message says that `events[i]` is `undefined`, so the `participants` property (or any other property, actually) cannot be read from it. Please create a minimal example code that we can inspect, run and debug (and of course produces the problem). – kapa Jul 15 '14 at 15:41
  • 1
    I imagine you're looping through this, perhaps in a `for` loop? Show us the snippet of code involving the `i` variable... – War10ck Jul 15 '14 at 15:42
  • @kapa no it is not. when i access events[0].name i can get the name of the event. the error is directly involved with the arrays inside the new_event var. – João Jul 15 '14 at 15:45
  • @João, do a console.log() of `i` when the code fails... it certainly is out of bounds. (Note aside, use `events.forEach(function(event){})` to iterate). – rvignacio Jul 15 '14 at 15:49
  • Can you paste your loop here ? Random guess : you're evaluating `length` outside the loop, but modifying it inside. – Jb Drucker Jul 15 '14 at 15:51
  • @JbDrucker rvignacio kapa edited code so you guys can see full loop – João Jul 15 '14 at 15:55
  • @João Look, we asked for a minimal example. Why paste here your full code? We are not interested in reading through all that. By creating a minimal example, you would already understand your code better and maybe find the problem yourself. – kapa Jul 15 '14 at 15:56
  • @kapa you guys asked for my for loop. my for loop prints the html inside the div. it woudn't be understood if you dont see the full code. – João Jul 15 '14 at 15:56
  • @João, you have a closures problem because of the ajax call. When the success function runs, the variable `i` doesn't have the value you expect. Read about closures and doing loops with asynchronous calls. – rvignacio Jul 15 '14 at 16:00
  • @Joao Seems like you are running AJAX calls in a for loop, which is not as easy as it would seem. SO already has lots of answers in this topic, please search using the keywords I have provided. – kapa Jul 15 '14 at 16:00
  • @kapa which keywords? – João Jul 15 '14 at 16:02
  • 1
    From here, I have only red half of your updated code and I can see 2 problems. 1st, Jquery `.each()` function is made for looping through DOM elements, not javascript objects. Use `$.each()` instead. Second, as AJAX is asynch, YOU CAN'T ASSUME that the `for loop` will be executed after the ajax call have finished – TCHdvlp Jul 15 '14 at 16:05

2 Answers2

3

Yo are having scope problems. You are doing a loop and then calling an asynchronous function inside. When jQuery executes the callback, the variable i in the outer scope has changed its value. There are lots of questions and answers about JavaScript scopes (a simple search will give you a lot of reading material).

What you can do to avoid these problems is using Array.prototype.forEach() instead of the for loop.

Instead of doing:

for(var i=0; i < events.length; i++){
                    $.ajax({...});
}

Use:

events.forEach(function(event){
    $.ajax({...
         success: function(){
          ...
             event.participants.push(new_participant)
          ...
         }
    });
});

The event value will be consistent because each function in the loop will have its own variable in its own scope.

This is a kinda difficult issue to grasp, I suggest you start by reading the MDN reference.

rvignacio
  • 1,710
  • 1
  • 18
  • 33
  • i have edited my code making the changes you suggested it had the same result. – João Jul 15 '14 at 17:54
  • That's because you're calling `alert()` right after the `$.ajax` calls. JavaScript IO is asynchronous, it won't execute the code in the order you write it, that's why callbacks are used. See [this question](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call/14220323). – rvignacio Jul 15 '14 at 18:20
  • OK now i had no errors, but i cant print the html elements because as you can see in my for loop i need to print 5 each time. and i cant do that without an index or something like it. – João Jul 15 '14 at 19:36
  • I need the ability to be able to make the loop coming from the last element to the first and discount 5 every time it. – João Jul 15 '14 at 20:00
0

It works if I do

events[0].participants.push(new_participant);
console.log(events);

http://jsfiddle.net/9YU2t/

As it has been said in comments, your mistake should come from i variable. Check its initialisation and value when used to insert content into your object.

EDIT : As the question has been updated. the variable i is the origin of the issue.

Also, in a pure programmatical way, I suggest to do in that order

new_event.participants.push(person_1);
new_event.participants.push(person_2);
....
events.push(new_event);
TCHdvlp
  • 1,334
  • 1
  • 9
  • 15