Raoot
Raoot

Reputation: 1771

Adding form fields and then applying JS functions to them?

I've followed the Railscast on creating a Nested Model Form and am successfully adding and removing fieldsets via Javascript as it demonstrates.

In my project I need to some on change functions to apply to the newly created fields; I have a price field and on changing this need to display a net return value to the user for example.

If I create the fields, save and then edit, my on change functions work fine but they do not work on any new fields/fieldsets added before the parent object is saved.

In short, how do I make my JS functions apply to fields created via JS?

The JS function I'm trying to apply to these newly created fields is as follows and this is contained in a document ready:

$('.ticket-price').each(function() { 
  $(this).change(function() {

    var ticket_price = $(this).val();

    if (ticket_price == 0) 
      {
      fee_rate = 0
      } 
    else if (ticket_price >= 0.01)
      {
      fee_rate = 0.10
      }

    var booking_fee = ticket_price * fee_rate
    var customer_pays = parseFloat(ticket_price) + parseFloat(booking_fee)
    var vendor_fee = ((customer_pays / 100) * 3.5) +0.2
    var vendor_receives = (parseFloat(ticket_price) - vendor_fee )

    $(this).parent().next().children('input.booking-fee').val(booking_fee.toFixed(2)).effect( "highlight", 
              {color:"#FFFF33"}, 1500 );

    $(this).parent().next().next().children('input.vendor-receives').val(vendor_receives.toFixed(2)).effect( "highlight", {color:"#FFFF33"}, 1500 );

  });

});

Would I be correct in thinking as this is in document ready, the new fields are therefore not seen by this? How do I go about getting them 'seen'?

EDIT: New version of code, where I get strange behaviour. Only the second on change event is seen and then the highlight occurs based on the number of times the change is made.....so if three changes were made to the ticket price field it 'pulses' yellow three times.

$(document).on('change', '.ticket-price', function() {
  $(this).change(function() {

    var ticket_price = $(this).val();

    if (ticket_price == 0) 
      {
      fee_rate = 0
      } 
    else if (ticket_price >= 0.01 && ticket_price <= 25.00)
      {
      fee_rate = 0.10
      }
    else if (ticket_price >= 25.01 && ticket_price <= 40.00)
      {
      fee_rate = 0.08
      }
    else if (ticket_price >= 40.01 && ticket_price <= 60.00)
      {
      fee_rate = 0.07
      }
    else if (ticket_price >= 60.01)
      {
      fee_rate = 0.06
      }

    var booking_fee = ticket_price * fee_rate
    var customer_pays = parseFloat(ticket_price) + parseFloat(booking_fee)
    console.log(customer_pays);
    var vendor_fee = ((customer_pays / 100) * 3.5) +0.2
    var vendor_receives = (parseFloat(ticket_price) - vendor_fee )

    console.log(booking_fee);
    console.log(vendor_receives);

    $(this).parent().next().children('input.booking-fee').val(booking_fee.toFixed(2)).effect( "highlight", 
              {color:"#FFFF33"}, 1500 );

    $(this).parent().next().next().children('input.vendor-receives').val(vendor_receives.toFixed(2)).effect( "highlight", {color:"#FFFF33"}, 1500 );

  });

});

Upvotes: 0

Views: 49

Answers (2)

Breno Gazzola
Breno Gazzola

Reputation: 2162

Do this:

$(document).on('change', '.ticket-price', function() { 
    var ticket_price = $(this).val();
    ...
});

This way instead of binding your event to the HTMLElements currently on page, you are telling jQuery to watch the entire document for changes on any elements with the 'ticket-price' class. Even ones that are added dynamically.

Here's a sample jsFiddle: http://jsfiddle.net/64eLt/2/

Upvotes: 1

Richard Peck
Richard Peck

Reputation: 76774

Okay, I think the problem you have is that your Javascript is not picking up the dynamically-added items


Dynamic DOM

Javascript (and JQuery by virtue of inheritance) works by binding elements in the DOM (Document Object Model) to events. These events are described by you with your functions, and Javascript basically adds "listeners" to the various elements you include

The problem you have is when you're updating the DOM, your new elements are not bound to any functions you assigned when the document loaded, thus preventing them from working

The solution to this, as pointed out by the other answer, is to delegate your function from the document to the elements you wish to change, like this:

 $(document).on("change", ".ticket_price",function() {
     //do stuff here
 });

Upvotes: 0

Related Questions