简体   繁体   中英

Bind click event to single select element on change

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');
    });
});

Updated fiddle

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');
  });
}
]

https://jsfiddle.net/ohnruubh/5/

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM