2

I have a JQuery FIddle properly running. It uses a JQUERY Steps PlugIn . Now if you run JQuery FIddle in the last step you will find three button "Save", "Previous" and "Finish". If I click on Save button I want to show an alert saying "you have been clicked". If you scroll to the bottom of the HTML Section in the JSFiddle you will find below code.

Code working fine:

// on Save button click
    $(".actions").on("click",".saveBtn",function(){
      alert("You have been clicked!");
    });
  });

Code not working:

 $( ".saveBtn" ).click(function() {
      alert("You have been clicked");
    });

Question: Why does the second code snippet not work?

tyler_mitchell
  • 1,727
  • 1
  • 19
  • 27
Unbreakable
  • 7,776
  • 24
  • 90
  • 171

4 Answers4

16

A short story about events:

Since your button with class .saveBtn is created dynamically it doesn't get initialized at document load. But in order to bind events to elements they normally need to be initialized on startup. Your button however gets created when all events are bound to elements already. So you need to do something called event delegation. This means that you listen to a specific event in the entire document for example. When the event fires you look up which element fired the event. This way even dynamically created elements can be selected. A common method for this is the following:

$(document).on('click', '.saveBtn', function(){
  alert("Dynamic button clicked. Hurray!");
});

This way you are telling the entire document to register click events and compare the source of the event with your selector, in this case .saveBtn.

hallleron
  • 1,972
  • 3
  • 13
  • 18
  • 1
    I see. does that mean that for every click event occuring in the entire page this code will be executed/checked? – Unbreakable Jul 24 '17 at 14:51
  • Yes that is true. But you can select the closest element (parent) possible that has been live since page load instead of "document". That minimizes the processing. Do you understand what I mean? – hallleron Jul 24 '17 at 14:52
  • 1
    Thank you so much. I learned something new today. You rock! :) – Unbreakable Jul 24 '17 at 14:52
  • Thanks for the kind words =) – hallleron Jul 24 '17 at 14:53
  • Even though this is correct, I would not recommend this solution, event listener for every click? All answers given are quick wins and explain why the class event listener does not work. But they are not efficient nor offer you the best practice – tyler_mitchell Jul 24 '17 at 14:59
  • Taht is why I said that you shouls use the closest parent possible as a click event listener :-) To use the entire document every time is bad practice, so I totally agree. But when you have the closest parent the performance loss is almost nothing. – hallleron Jul 24 '17 at 15:22
  • 1
    Now all this is making sense to me. The closest I am the less overhead. :) yay! – Unbreakable Jul 24 '17 at 15:32
3

It is not working because you are dynamically creating the button, move the function to after this line $(document).find(".actions ul").prepend(saveBtn) and it will work.

$(document).find(".actions ul").prepend(saveBtn)
$(".saveBtn").click(function() {
    alert("You have been clicked");
});

here is an update of your fiddle working https://jsfiddle.net/mjyq4oda/5/

CumminUp07
  • 1,936
  • 1
  • 8
  • 21
  • Thank you so much. Actually I am a beginner. can you kindly explain why the first code snippet worked flawlessly in the first place. I mean why some thing like this ` $(".actions").on("click",".saveBtn",function()` worked flawlessly irrespective of the placement of the code. – Unbreakable Jul 24 '17 at 14:44
  • If you can tell me some link which I can read as why the first code snippet works fine, – Unbreakable Jul 24 '17 at 14:45
  • the `.on` method replaced the `.live` method which attaches even handles to selectors now and in the future. the `.click` method only attaches to current selectors here is a link on the `.live` method http://api.jquery.com/live/ – CumminUp07 Jul 24 '17 at 14:46
  • 1
    @Unbreakable look at hallleron's answer, it explains it well – CumminUp07 Jul 24 '17 at 14:48
1

beause your save button is dynamic. it is created after some click events. try on function instead of click

  $(document).on("click", ".saveBtn", function() {
        alert("You have been clicked")
    });
Badiparmagi
  • 1,285
  • 1
  • 14
  • 24
1

You are adding the button dynamically on step change, your event listener is is initialised when there are no buttons with class saveBtn.

$( ".saveBtn" ) returns nothing.

Instead of removing it and appending it on step change, just hide and show. This would be better.

See working fiddle

This uses the init of jQuery steps to add the button once (not every step change).

onInit: function (event, currentIndex) { 
    var saveA = $("<a>").attr("href","#").addClass("saveBtn").text("Save");
    var saveBtn = $("<li>").attr("aria-disabled",false).append(saveA);
    $(document).find(".actions ul").prepend(saveBtn);
    $(".actions").find(".saveBtn").hide();
}

Then on step change we just show/hide:

onStepChanged:function (event, currentIndex, newIndex) {
    if(currentIndex == 2)
        $(".actions").find(".saveBtn").show();
    else
      $(".actions").find(".saveBtn").hide();

    return true;
}
tyler_mitchell
  • 1,727
  • 1
  • 19
  • 27
  • Your solution even makes more sense. As I added the button from the get go, So I don't need to take any pain of adding explicit event listener. I can use my basic JQuery $() selector directly on the button itself. so nothing is dynamic. Am I right? – Unbreakable Jul 24 '17 at 15:10
  • You are correct, as you can see in the fiddle i am using the .saveBtn event listener you wanted to use. – tyler_mitchell Jul 24 '17 at 15:14