I have multiple select
elements. When one of them is changed I want to bind a click event only to its next element with the .btn
class. This is my code:
<div class="whole">
<ul>
<li>
first
<select>
<option></option>
<option>reject</option>
<option>hire</option>
</select>
<span class="btn">button</span>
</li>
<li>
second
<select>
<option></option>
<option>reject</option>
<option>hire</option>
</select>
<span class="btn">button</span>
</li>
<li>
third
<select>
<option></option>
<option>reject</option>
<option>hire</option>
</select>
<span class="btn">button</span>
</li>
</ul>
</div>
$('select').change(function() {
var $changed = $(this);
bindClick($changed);
});
var bindClick = function($el){
$('.whole').on('click', $el.next(), function() {
console.log('ciao');
});
}
What happens is that after a select
is changed click is bound on every .btn
element. I am using jQuery. Here is an example Fiddle
Your second argument to on() is considered as data not as a selector(selector should be a string)
The verison of on
you are using the $el.next()
value is considered as custom data
(if the second argument is not a string) for the event and the event is bound to the whole
element - does not use event delegation
Instead you can directly bind the handler to the $el.next()
element
$('select').change(function() { var $changed = $(this); bindClick($changed); }); var bindClick = function($el) { $el.next().on('click', function() { snippet.log('change: ' + this.innerText); }); $('.whole').on('click', $el.next(), function(e) { snippet.log('whole click:' + e.data.text()); console.log('event', e) console.log('data', e.data) }); }
li { padding: 2em; } .btn { color: red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script> <div class="whole"> <ul> <li>first <select> <option></option> <option>reject</option> <option>hire</option> </select> <span class="btn">button 1</span> </li> <li>second <select> <option></option> <option>reject</option> <option>hire</option> </select> <span class="btn">button 2</span> </li> <li>third <select> <option></option> <option>reject</option> <option>hire</option> </select> <span class="btn">button 3</span> </li> </ul> </div>
The issue you have is that the delegate signature of on()
expects a string selector in the second property, not a jQuery object.
However you can improve the logic by using the off()
method to remove any previously added click handlers and also by reducing any confusion the user may have by only displaying a button when it can be clicked. Try this:
$('select').change(function() {
$('.btn').off('click').removeClass('active');
$(this).next('.btn').addClass('active').click(function() {
console.log('ciao');
});
});
Try this, Working Fiddle
$('select').change(function() {
var $changed = $(this);
bindClick($changed.closest('li').next().find('select')); //pass the next select element
});
var bindClick = function($el){
$el.on('click',function(){ // bind event directly to that element, without using event delagation
console.log('ciao');
});
}
Also the problem was you were passing a Jquery Object as your second parameter. it should be a string which represents a selector
Try this
[
$('select').change(function() {
var $changed = $(this);
bindClick($changed);
});
var bindClick = function($el){
$el.next().addClass('active')
$('.whole').off('click','.active')
$('.whole').on('click','.active',function(){
console.log('ciao');
});
}
]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.