0

[Not duplicate] - I checked the Event binding on dynamically created elements? question, and its answer is actually the start point of my question. I start off with $parent.on('click', '.specificChild' ... etc.). I already know that (see it for wrapper1). The first part of my question has nothing to do with the referenced SO question.


Within a parent element, I want to create a child element and then grand-child elements, and have a click event on a grand-child element.

Is it possible to pre-define child element and also pre-define the click event, even before the child/grand-child elements are created ?

// wrapper1 related -- it works
var $wrapper1 = $('.wrapper1');
var $number1 = $wrapper1.find('.number');
$wrapper1.on('click', '.incrementButton', function () {
    var currentVal = parseInt($number1.html(), 10);
    $number1.html(currentVal + 1);
});


// wrapper2 related - doesn't work
// define the elements upfront
var $wrapper2 = $('.wrapper2');
var $foundation = $wrapper2.find('.foundation');
var $number2 = $wrapper2.find('.number');
$wrapper2.on('click', '.incrementButton', function () {
    var currentVal = parseInt($number2.html(), 10);
    $number2.html(currentVal + 1);
});


$wrapper2.html('<div class="foundation"></div>');
var htmlContent = '' +
        '<div class="arithmetic">' +
        '    <div class="number">1</div>' +
        '    <div class="incrementButton">+ 1</div>' +
        '</div>';
$foundation.html(htmlContent);
.wrapper1, .wrapper2 {
    background-color: #E8EAF6;
    padding: 1em;
    width: 12em;;
    margin: 1em;
}
.foundation {
    background-color: #9FA8DA;
    padding: 1em;
}
.arithmetic {
    background-color: #5C6BC0;
    padding: 1em;
    overflow: hidden;
}
.number {
    width: 1.5em;
    height: 1.5em;
    text-align: center;
    line-height: 1.5;
    background-color: white;
    float: left;
    color: #3949AB;
    margin-right: 1em;
}
.incrementButton {
    overflow: hidden;
    height: 1.5em;
    line-height: 1.5;
    text-align: center;
    background-color: #3949AB;
    border: 1px solid white;
    color: #E8EAF6;
}
.incrementButton:hover {
    cursor: pointer;
    background-color: #283593;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper1">
  <div class="foundation">
    <div class="arithmetic">
      <div class="number">1</div>
      <div class="incrementButton">+ 1</div>
    </div>
  </div>
</div>

<div class="wrapper2"></div>

More specifically, the question is:

  1. How can I define $foundation before its creation ? i.e. before this line $wrapper2.html('<div class="foundation"></div>') ?
  2. How can I bind the click function to incrementButton within wrapper2, even before the creation of the incrementButton element ?
Community
  • 1
  • 1
Kaya Toast
  • 5,267
  • 8
  • 35
  • 59
  • If the context is of any use, I am actually using handlebarsjs to create the child and grand-child elements, and my problem is that I am unable to bind elements upfront. – Kaya Toast Jan 07 '16 at 16:42
  • Typically, you would apply `on()` to the parent which your element in question exists. – user1032531 Jan 07 '16 at 16:43
  • Instead of your foundation variable, why aren't you just doing `$wrapper2.html(htmlContent);`? https://jsfiddle.net/j08691/n4swj92g/ – j08691 Jan 07 '16 at 16:54
  • That's because the `htmlContent` is smaller unit of a handlebars template, re-used/repeated many times. And the `foundation` is another handlebars template, re-used a few times. Hence, keeping them separate. – Kaya Toast Jan 07 '16 at 16:56

1 Answers1

2

To bind event for future elements I use:

$(document).on('click', '.wrapper2 .incrementButton'.....

In past jQuery version you could use the live method.

Your section to create the wrapper2 needed a little rearrangemnet.

Use append instead of html methods.

No, you cannot execute:

var $foundation = $wrapper2.find('.foundation');

before the elements with class '.foundation' is created.

My proposal is:

$(function() {
  // wrapper1 related -- it works
  var $wrapper1 = $('.wrapper1');
  var $number1 = $wrapper1.find('.number');
  $wrapper1.on('click', '.incrementButton', function () {
    var currentVal = parseInt($number1.html(), 10);
    $number1.html(currentVal + 1);
  });


  var $wrapper2 = $('.wrapper2');

  $wrapper2.append('<div class="foundation"></div>');

  var $foundation = $wrapper2.find('.foundation');
  var htmlContent = '' +
      '<div class="arithmetic">' +
      '    <div class="number">1</div>' +
      '    <div class="incrementButton">+ 1</div>' +
      '</div>';
  $foundation.append(htmlContent);

  var $number2 = $wrapper2.find('.number');
  $(document).on('click', '.wrapper2 .incrementButton', function () {
    var currentVal = parseInt($number2.html(), 10);
    $number2.html(currentVal + 1);
  });
});
.wrapper1, .wrapper2 {
  background-color: #E8EAF6;
  padding: 1em;
  width: 12em;;
  margin: 1em;
}
.foundation {
  background-color: #9FA8DA;
  padding: 1em;
}
.arithmetic {
  background-color: #5C6BC0;
  padding: 1em;
  overflow: hidden;
}
.number {
  width: 1.5em;
  height: 1.5em;
  text-align: center;
  line-height: 1.5;
  background-color: white;
  float: left;
  color: #3949AB;
  margin-right: 1em;
}
.incrementButton {
  overflow: hidden;
  height: 1.5em;
  line-height: 1.5;
  text-align: center;
  background-color: #3949AB;
  border: 1px solid white;
  color: #E8EAF6;
}
.incrementButton:hover {
  cursor: pointer;
  background-color: #283593;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<div class="wrapper1">
    <div class="foundation">
        <div class="arithmetic">
            <div class="number">1</div>
            <div class="incrementButton">+ 1</div>
        </div>
    </div>
</div>

<div class="wrapper2"></div>
gaetanoM
  • 41,594
  • 6
  • 42
  • 61
  • Thanks. Can you also respond to the first part of my question ? Can I declare `foundation` before it is created ? You moved its declaration to after its creation. – Kaya Toast Jan 07 '16 at 17:01
  • @KayaToast I updated my answer adding the second answer: the answer to your second question is no. Is there any problem? – gaetanoM Jan 07 '16 at 17:13