Ichorville
Ichorville

Reputation: 944

JQuery event binding getting overriden

I'm trying to bind events to entities inside a certain for loop inside a for loop.

Basically it's a for loop inside a for loop and the methods do bind. But my problem is that when ever I interact with the inner loop implemented method first, then the outer loop implemented method, then only the outer loop implemented method would work and the inner level implemented method will not work anymore.

Same happens if I start interacting with the outer loop implemented method where only that method would work and the inner loop implemented method will not work at all. This is what I have tried so far:

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

for (var i in result) {
  if (result[i].children) {
    // fill outer layer entities with children
    tree.innerHTML +=
      '<div id="layer_one_title_' + [i] + '" class="title">' +
      '<i class="dropdown icon"></i>' +
      '<i class="folder icon"></i>' + result[i].text +
      '<i class="plus icon lev_one_add" ></i>' +
      '</div>' +
      '<div id="layer_one_content_' + [i] + '" class="content active"></div>';

    $('#layer_one_title_' + [i]).on('click', '.lev_one_add', function(event) {
      newFirstNode(result[i], event);
    });

    let layer_one_content = document.getElementById('layer_one_content_' + [i]);
    for (var j in result[i].children) {
      if (result[i].children[j].children) {
        // fill inner layer entities with children
        layer_one_content.innerHTML +=
          '<div id="layer_one_' + [i] + '_' + [j] + '" class="accordion layer_one">' +
          '<div id="layer_two_title_' + [i] + '_' + [j] + '" class="title">' +
          '<i class="dropdown icon"></i>' +
          '<i class="folder icon"></i>' + result[i].children[j].text +
          '<i class="plus icon lev_two_add"></i>' +
          '</div>' +
          '<div id="layer_two_content_' + [i] + '_' + [j] + '" class="content active"></div>' +
          '</div>';

        $('#layer_two_title_' + [i] + '_' + [j]).on('click', '.lev_two_add', function(event) {
          newFirstNode(result[i], event);
        });

Any idea what I'm doing wrong here?

Upvotes: 0

Views: 62

Answers (1)

Yeshan Jay
Yeshan Jay

Reputation: 1413

I'm assuming that you're using jQuery here. See if the code below works out for you. (Altered your code).

Btw, didn't test this code. Hope it works :P

// Note: Trying my best to prevent binding events and injecting html within a loop.

// Find the parent element first.
let $tree = $("#tree");

// Bind a delegate event on to the parent for a child click.
$tree.on('click', ".lev_one_add", result, function (event) {
    let $self = $(this);
    let result = event.data; // Access the data passed when binding this event (third param in this event statement).
    let index = $self.data("index"); // Access the index which was set as an attribute in the html format ("data-index").

    newFirstNode(result[index], event);
});

$tree.on('click', '.layer_two_container .lev_two_add', result, function (event) {
    let $self = $(this);
    let result = event.data; // Access the data passed when binding this event (third param in this event statement).
    let parentIndex = $self.data("pindex"); // Access the index which was set as an attribute in the html format ("data-pindex").
    let index = $self.data("index"); // Access the index which was set as an attribute in the html format ("data-index").

    if (result[parentIndex] && result[parentIndex].children[index]) {
        newSecondNode(result[parentIndex], event);
    }
});


let htmlChilds = "";
for (var i in result) {
    if (result[i].children) {
        // Append the html as a string all at once instead of injecting each html child at a time.
        // (This way is performance efficient)
        htmlChilds +=
            '<div id="layer_one_title_' + [i] + '" class="title">' +
            '<i class="dropdown icon"></i>' +
            '<i class="folder icon"></i>' + result[i].text +

            // Added an attribute "data-index" to hold the index.
            '<i class="plus icon lev_one_add" data-index="' + [i] + '" ></i>' +
            '</div>' +

            // Open the .layer_two_container div.
            '<div id="layer_one_content_' + [i] + '" class="content active layer_two_container">';


        for (var j in result[i].children) {
            if (result[i].children[j].children) {
                htmlChilds +=
                    '<div id="layer_one_' + [i] + '_' + [j] + '" class="accordion layer_one">' +
                    '<div id="layer_two_title_' + [i] + '_' + [j] + '" class="title">' +
                    '<i class="dropdown icon"></i>' +
                    '<i class="folder icon"></i>' + result[i].children[j].text +

                    // Added attributes "data-pindex" and "data-index" to hold indexes of parent and child.
                    '<i class="plus icon lev_two_add" data-pindex="' + [i] + '" data-index="' + [j] + '"></i>' +
                    '</div>' +
                    '<div id="layer_two_content_' + [i] + '_' + [j] + '" class="content active"></div>' +
                    '</div>';
            }
        }

        // Close the .layer_two_container div.
        htmlChilds += '</div>';
    }
}

// Inject the children html into the parent node.
$tree.html(htmlChilds);

Upvotes: 1

Related Questions