Присоединить событие к динамическим элементам в javascript
Я пытаюсь динамически вставлять данные html в список, который динамически создается, но когда я пытаюсь подключить событие onclick для кнопки, которая динамически создается, событие не запускается. Решение было бы действительно оценено.
Код Javascript:
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('btnSubmit').addEventListener('click', function () {
var name = document.getElementById('txtName').value;
var mobile = document.getElementById('txtMobile').value;
var html = '<ul>';
for (i = 0; i < 5; i++) {
html = html + '<li>' + name + i + '</li>';
}
html = html + '</ul>';
html = html + '<input type="button" value="prepend" id="btnPrepend" />';
document.getElementsByTagName('form')[0].insertAdjacentHTML('afterend', html);
});
document.getElementById('btnPrepend').addEventListener('click', function () {
var html = '<li>Prepending data</li>';
document.getElementsByTagName('ul')[0].insertAdjacentHTML('afterbegin', html);
});
});
Код HTML:
<form>
<div class="control">
<label>Name</label>
<input id="txtName" name="txtName" type="text" />
</div>
<div class="control">
<label>Mobile</label>
<input id="txtMobile" type="text" />
</div>
<div class="control">
<input id="btnSubmit" type="button" value="submit" />
</div>
</form>
Ответы
Ответ 1
Это связано с тем, что ваш элемент создается динамически. Вы должны использовать делегирование события для обработки события.
document.addEventListener('click',function(e){
if(e.target && e.target.id== 'brnPrepend'){
//do something
}
});
JQuery делает это проще:
$(document).on('click','#btnPrepend',function(){//do something})
Вот статья о делегировании события
Ответ 2
Существует обходное решение путем захвата кликов по document.body
, а затем проверки целевого объекта.
document.body.addEventListener( 'click', function ( event ) {
if( event.srcElement.id == 'btnSubmit' ) {
someFunc();
};
} );
Ответ 3
Вы должны прикрепить событие после вставки элемента, например:
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('btnSubmit').addEventListener('click', function() {
var name = document.getElementById('txtName').value;
var mobile = document.getElementById('txtMobile').value;
var html = '<ul>';
for (i = 0; i < 5; i++) {
html = html + '<li>' + name + i + '</li>';
}
html = html + '</ul>';
html = html + '<input type="button" value="prepend" id="btnPrepend" />';
document.getElementsByTagName('form')[0].insertAdjacentHTML('afterend', html);
document.getElementById('btnPrepend').addEventListener('click', function() {
var html = '<li>Prepending data</li>';
document.getElementsByTagName('ul')[0].insertAdjacentHTML('afterbegin', html);
});
});
});
<form>
<div class="control">
<label>Name</label>
<input id="txtName" name="txtName" type="text" />
</div>
<div class="control">
<label>Mobile</label>
<input id="txtMobile" type="text" />
</div>
<div class="control">
<input id="btnSubmit" type="button" value="submit" />
</div>
</form>
Ответ 4
Вы можете сделать что-то похожее на это:
// Get the parent to attatch the element into
var parent = document.getElementsByTagName("ul")[0];
// Create element with random id
var element = document.createElement("li");
element.id = "li-"+Math.floor(Math.random()*9999);
// Add event listener
element.addEventListener("click", EVENT_FN);
// Add to parent
parent.appendChild(element);
Ответ 5
var __ = function(){
this.context = [];
var self = this;
this.selector = function( _elem, _sel ){
return _elem.querySelectorAll( _sel );
}
this.on = function( _event, _element, _function ){
this.context = self.selector( document, _element );
document.addEventListener( _event, function(e){
var elem = e.target;
while ( elem != null ) {
if( "#"+elem.id == _element || self.isClass( elem, _element ) || self.elemEqal( elem ) ){
_function( e, elem );
}
elem = elem.parentElement;
}
}, false );
};
this.isClass = function( _elem, _class ){
var names = _elem.className.trim().split(" ");
for( this.it = 0; this.it < names.length; this.it++ ){
names[this.it] = "."+names[this.it];
}
return names.indexOf( _class ) != -1 ? true : false;
};
this.elemEqal = function( _elem ){
var flg = false;
for( this.it = 0; this.it < this.context.length; this.it++ ){
if( this.context[this.it] === _elem && !flg ){
flg = true;
}
}
return flg;
};
}
function _( _sel_string ){
var new_selc = new __( _sel_string );
return new_selc;
}
Теперь вы можете зарегистрировать событие как,
_( document ).on( "click", "#brnPrepend", function( _event, _element ){
console.log( _event );
console.log( _element );
// Todo
});
Поддержка браузера
chrome - 4.0, Edge - 9.0, Firefox - 3.5 Safari - 3.2, Opera - 10.0 и выше
Ответ 6
Я создал небольшую библиотеку, чтобы помочь с этим: Исходный код библиотеки на GitHub
<script src="dynamicListener.min.js"></script>
<script>
// Any 'li' or element with class '.myClass' will trigger the callback,
// even elements created dynamically after the event listener was created.
addDynamicEventListener(document.body, 'click', '.myClass, li', function (e) {
console.log('Clicked', e.target.innerText);
});
</script>
Функциональность аналогична jQuery.on().
Библиотека использует метод Element.matches() для проверки целевого элемента с данным селектором. Когда событие инициируется, обратный вызов вызывается только в том случае, если целевой элемент соответствует заданному селектору.
Ответ 7
Разница в том, как вы создаете и добавляете элементы в DOM.
Если вы создаете элемент с помощью document.createElement
, добавьте прослушиватель событий и добавьте его в DOM. Ваши события будут срабатывать.
Если вы создаете элемент в виде строки, подобной этой: html + = "<li> test </li>" ', технически это просто строка. Строки не могут иметь слушателей событий.
Одним из решений является создание каждого элемента с document.createElement
а затем добавление их непосредственно в элемент DOM.
// Sample
let li = document.createElement('li')
document.querySelector('ul').appendChild(li)
Ответ 8
Я сделал простую функцию для этого.
Функция _case
позволяет вам не только получить цель, но и получить родительский элемент, с которым вы связываете событие.
Функция обратного вызова возвращает событие, которое содержит цель (evt.target
) и родительский элемент, соответствующий селектору (evt._this
). Здесь вы можете делать то, что вам нужно после нажатия на элемент.
Я еще не решил, что лучше, if-else
или switch
var _case = function(evt, selector, cb) {
var _this = evt.target.closest(selector);
if (_this && _this.nodeType) {
evt._this = _this;
cb(evt);
return true;
} else { return false; }
}
document.getElementById('ifelse').addEventListener('click', function(evt) {
if (_case(evt, '.parent1', function(evt) {
console.log('1: ', evt._this, evt.target);
})) return false;
if (_case(evt, '.parent2', function(evt) {
console.log('2: ', evt._this, evt.target);
})) return false;
console.log('ifelse: ', this);
})
document.getElementById('switch').addEventListener('click', function(evt) {
switch (true) {
case _case(evt, '.parent3', function(evt) {
console.log('3: ', evt._this, evt.target);
}): break;
case _case(evt, '.parent4', function(evt) {
console.log('4: ', evt._this, evt.target);
}): break;
default:
console.log('switch: ', this);
break;
}
})
#ifelse {
background: red;
height: 100px;
}
#switch {
background: yellow;
height: 100px;
}
<div id="ifelse">
<div class="parent1">
<div class="child1">Click me 1!</div>
</div>
<div class="parent2">
<div class="child2">Click me 2!</div>
</div>
</div>
<div id="switch">
<div class="parent3">
<div class="child3">Click me 3!</div>
</div>
<div class="parent4">
<div class="child4">Click me 4!</div>
</div>
</div>
Ответ 9
Я знаю, что тема слишком старая, но я посвятил себя нескольким минутам, чтобы создать очень полезный код, который отлично работает и очень легко работает с использованием чистого языка JAVASCRIPT
.
Вот код с простым примером:
String.prototype.addEventListener=function(eventHandler, functionToDo){
let selector=this;
document.body.addEventListener(eventHandler, function(e){
e=(e||window.event);
e.preventDefault();
const path=e.path;
path.forEach(function(elem){
const selectorsArray=document.querySelectorAll(selector);
selectorsArray.forEach(function(slt){
if(slt==elem){
if(typeof functionToDo=="function") functionToDo(el=slt, e=e);
}
});
});
});
}
// And here is how we can use it actually !
"input[type='number']".addEventListener("click", function(element, e){
console.log( e ); // Console log the value of the current number input
});
<input type="number" value="25">
<br>
<input type="number" value="15">
<br><br>
<button onclick="addDynamicInput()">Add a Dynamic Input</button>
<script type="text/javascript">
function addDynamicInput(){
const inpt=document.createElement("input");
inpt.type="number";
inpt.value=Math.floor(Math.random()*30+1);
document.body.prepend(inpt);
}
</script>