-1

Hope figured the question right. So, I have some radios, which my CMS loads as product options. On the same page I have an AJAX filter, which can load exactly the same radios to that exact place.

The trouble is, that I'm unable to change the total price with this dynamically created radios, but previous ones works just fine. Run the snippet for best understanding.

$('#add').on('click', function() {
  if (!$('#price_3').length) {
    $('#multiply').before('<input type="radio" name="radios" id="price_3" value="3"> <label for="price_3">Generated by AJAX</label> <br><br>');
    $(this).remove();
  }
})

$("input").bind("change keyup", function() {
  var price = 100;

  if ($('#price_1').is(':checked')) {
    price += 100;
  };

  if ($('#price_2').is(':checked')) {
    price += 200;
  };

  if ($('#price_3').is(':checked')) {
    price += 300;
    $(".total").append("&nbsp;<- doesn't change the price");
    $(".info").html("<br><br> Actually adds +300, but not live");
  };

  if ($('#multiply').is(':checked')) {
    price *= 2;
  };

  $(".total").html(price);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post">
  <input type="radio" name="radios" id="price" value="0" checked>
  <label for="price">I'm a base</label>
  <br>
  <input type="radio" name="radios" id="price_1" value="1">
  <label for="price_1">Here by default</label>
  <br>
  <input type="radio" name="radios" id="price_2" value="2">
  <label for="price_2">Here by default 2</label>
  <br>
  <input type="checkbox" name="multiply" id="multiply" value="multiply">
  <label for="multiply">Multiply by 2</label>
  <br>
  <input type="button" id="add" value="Add a radio">
  <br>
  <span class="total">100</span>
  <span class="info"></span>
</form>

Edit 1. The thing is not regarded to async ajax or on, because it actually does additions, but just doesn't show it on change. I'm messing something with events.

  • Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Liam Jan 27 '17 at 16:24
  • `.on()` is async FYI – Liam Jan 27 '17 at 16:25
  • This has been asked and answered dozens of times. You must delegate the event handler. Your events will not work on dynamically added DOM elements. It's in the jQuery documentation. – Chris Caviness Jan 27 '17 at 16:28
  • input doesn't exist when you bind, so it isn't bond. – Andrew Bone Jan 27 '17 at 16:32
  • I think delegation is already applied. Isn't it? =) – Azamat Safarov Jan 27 '17 at 16:36
  • Possible duplicate of [Event binding on dynamically created elements?](http://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – freedomn-m Jan 27 '17 at 16:44
  • You're adding events inside another event - never a good idea. `$('input').bind...` is not using event delegation, so doesn't bind to `#price_3`. – freedomn-m Jan 27 '17 at 16:47
  • `$("form").on("change")` will only bind **after you've already changed one of the other values**. So works fine if you click `#price_2` *first* then the new radio. Because of adding events inside other events, if you click 2,3,2,3,2, then add, then the new one, you get "doesn't change the price" multiple times. – freedomn-m Jan 27 '17 at 16:48

2 Answers2

0

The event handler is run without any of the other event happening. So price is never being set. Delegate the event handler and get you data however from that.

For example:

$('#add').on('click', function() {
    if(!$('#price_3').length) {
    $(this).before('<input type="radio" name="radios" id="price_3" value="3"> <label for="price_3">Generated by AJAX</label> <br><br>');
  }
})

$("form").bind("change keyup", "input", function (e) {
  var price = 299;

  switch (e.target.id) {
    case 'price_1':
      price += 100;
      break;
    case 'price_2':
      price += 200;
      break;
    case 'price_3':
      price += 300;
      break;
  };

  $(".total").html(price);
});


<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post">
    <input type="radio" name="radios" id="price" value="0" checked> <label for="price">I'm a base</label> <br>
    <input type="radio" name="radios" id="price_1" value="1"> <label for="price_1">Here by default</label> <br>
    <input type="radio" name="radios" id="price_2" value="2"> <label for="price_2">Here by default 2</label> <br>
    <input type="button" id="add" value="Add a radio"> <br> <br>
    <span class="total">299</span>
    <span class="info"></span>
</form>
JacobS
  • 606
  • 5
  • 13
  • if you're gonna do that, you may as well just compress it down all the way $("form").bind("change keyup", "input", function(e) {$(".total").html(299 + (e.target.value * 100))}); – Andrew Bone Jan 27 '17 at 16:42
  • Thank you for your reply. Works in form you provided, but my code was a simple example. The actual script is much complicated, so I cannot use `switch`. – Azamat Safarov Jan 27 '17 at 16:43
  • @AzamatSafarov what about this https://jsfiddle.net/2k68fote/ presuming your value field has meaning. – Andrew Bone Jan 27 '17 at 16:44
  • @AndrewBone , nope. This radios are the product options. They can cost from $1 to $1000. I also couldn't use this solution because the product has many other options (checkboxes, inputs), for functionality of which the `price` var should stay outside the `form` `keyup`. – Azamat Safarov Jan 27 '17 at 16:53
0

As expected, I was messing up with events. So, the solution is to not to use new events for dynamically added radios inside existing change keyup, and delegate that events to new crated radios.

$("form").bind("change keyup", "#price_3", function() { // note, that I'm using very big form in the project, so I'm unable to delegate just to input
  var price = 100;

  if ($('#price_1').is(':checked')) {
    price += 100;
  };

  if ($('#price_2').is(':checked')) {
    price += 200;
  };

  if ($('#price_3').is(':checked')) {
    price += 300;
  };

  $(".total").html(price);
})

See the fiddle for details: https://jsfiddle.net/shnn032o/8/