Ionică Bizău
Ionică Bizău

Reputation: 113385

Delegate events for subelements including the current element

I want to make a general jQuery code which will catch all the submit events of <form> subelements including the container element (in case it's a form).

The cases are:

The container is a form

<form>
    <button>hi</button>
</form>

The container is another element containing forms

<div>
    <form>
        <button>submit</button>
    </form>
</div>

What's the cleanest code to do this?

My current solution is the following:

function submit(e) {
   // do something
}

$(containerSelectorOrjQueryObject).on("submit", "form", submit);
$(containerSelectorOrjQueryObject).on("submit", submit);

However, I'd be happy to know if there is a better solution, using just one on call.

Upvotes: 5

Views: 136

Answers (2)

Brian Swift
Brian Swift

Reputation: 5926

You can use a class attribute for this as a way to set up a delegate to catch the submit event of any child form no matter what the parent element is. Because it is a delegate, this will also catch anything fired by elements that have been dynamically added as well.

Example that includes a single form scenario, multiple forms in div scenario, and a button to add a form dynamically:

var alreadyAdded;

function submit(e) {
    // do something
    alert(e.target.name);
    return false;
}

$("body").on("submit", ".outerContainer", submit);

$("#addAnotherDynamically").on("click", function(e) {
    if (typeof(alreadyAdded) === "undefined") {
        alreadyAdded = true;
        $("#test2").append("<form name='form4'><button>submit 4</button></form>");
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<body>
    <form id="test1" name="form1" class="outerContainer">
        <button>submit 1</button>
    </form>
    
    <div id="test2" class="outerContainer">
        <form name="form2">
            <button>submit 2</button>
        </form>
        <form name="form3">
            <button>submit 3</button>
        </form>        
    </div>
    
    <br>
    <button id="addAnotherDynamically">Add another form</button>
</body>

Upvotes: 1

Luizgrs
Luizgrs

Reputation: 4873

Submit events, like other event, bubbles across the DOM, so attaching an submit event listener to the form itself or to any of its parents will work and you can even cancel your submit there.

To always get the form in which the submit was triggered use e.target instead of this within the event listener method.

See this example:

function onSubmit(e){
  e.preventDefault();
   document.getElementById('d3').innerHTML += 'Submit catched in ' + e.currentTarget.tagName + '#' + e.currentTarget.id + ' for ' + e.target.tagName + '#' + e.target.id + '<br/>';  
}

$(function(){
  $('#d1').on('submit', onSubmit);
  $('#f2').on('submit', onSubmit);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="d1">
   <form id="f1">
  <input type="submit" value="Event Listener on DIV" />
  </form>  
</div>


<div id="d2">
   <form id="f2">
  <input type="submit" value="Event Listener on Form" />
  </form>  
</div>

<div id="d3">
</div>

Running it and clicking on the buttons you can see that using the same on call you can attach evest to the form itself or its parent and it will work as expected.

So, you can go with only the line below and it will work fine:

$(containerSelectorOrjQueryObject).on("submit", submit);

Upvotes: 0

Related Questions