자바스크립트에서 동적 요소에 이벤트 첨부
동적으로 생성된 목록에 html 데이터를 동적으로 삽입하려고 하는데 동적으로 생성된 버튼에 대해 on click 이벤트를 첨부하려고 하면 이벤트가 발생하지 않습니다.해결해 주시면 정말 감사하겠습니다.
자바스크립트 코드:
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>
이것은 당신의 요소가 동적으로 생성되어 나중에 DOM에 첨부되지만 당신의addEventListener
이전에 이미 발생한 호출입니다.이벤트 위임을 사용하여 이벤트를 처리해야 합니다.
document.addEventListener("click", function(e){
const target = e.target.closest("#btnPrepend"); // Or any other selector.
if(target){
// Do something with `target`.
}
});
closest
클릭이 대상 요소 내부 어디에서나 발생했거나 대상 요소 자체인지 확인합니다.예를 들어, 이것은 당신의 것이 아닌 경우에 유용합니다.<input id="btnPrepend"/>
은이 .<button id="btnPrepend"><i class="icon">+</i> prepend</button>
그리고 당신은 클릭을 했습니다.<i class="icon">+</i>
.
jQuery를 사용하면 더욱 쉬워집니다.
$(document).on("click", "#btnPrepend", function(){
// Do something with `$(this)`.
});
이벤트 위임에 관한 기사입니다.
클릭 수를 캡처하여 해결 방법이 있습니다.document.body
이벤트 대상을 확인합니다.
document.body.addEventListener( 'click', function ( event ) {
if( event.target.id == 'btnSubmit' ) {
someFunc();
};
} );
DOM에서 요소를 생성하고 추가하는 방법에 차이가 있습니다.
요소를 생성할 경우document.createElement
, 이벤트 수신기를 추가하고 DOM에 추가합니다.이벤트가 시작됩니다.
html += "<li>test</li>"'와 같은 문자열로 요소를 만들면 요소는 엄밀히 말하면 문자열에 불과합니다.문자열에는 이벤트 수신기를 사용할 수 없습니다.
하나의 해결책은 다음과 같이 각 요소를 생성하는 것입니다.document.createElement
그런 다음 DOM 요소에 직접 추가합니다.
// Sample
let li = document.createElement('li')
document.querySelector('ul').appendChild(li)
요소를 삽입한 후에 이벤트를 첨부해야 합니다. 예를 들어 전역 이벤트를 첨부하지 않는 경우document
삽입된 요소에 대한 특정 이벤트입니다.
예.
document.getElementById('form').addEventListener('submit', function(e) {
e.preventDefault();
var name = document.getElementById('txtName').value;
var idElement = 'btnPrepend';
var html = `
<ul>
<li>${name}</li>
</ul>
<input type="button" value="prepend" id="${idElement}" />
`;
/* Insert the html into your DOM */
insertHTML('form', html);
/* Add an event listener after insert html */
addEvent(idElement);
});
const insertHTML = (tag = 'form', html, position = 'afterend', index = 0) => {
document.getElementsByTagName(tag)[index].insertAdjacentHTML(position, html);
}
const addEvent = (id, event = 'click') => {
document.getElementById(id).addEventListener(event, function() {
insertHTML('ul', '<li>Prepending data</li>', 'afterbegin')
});
}
<form id="form">
<div>
<label for="txtName">Name</label>
<input id="txtName" name="txtName" type="text" />
</div>
<input type="submit" value="submit" />
</form>
element.matchs의 장점을 활용한 재사용 가능한 기능은 다음과 같습니다.
function delegate_event(event_type, ancestor_element, target_element_selector, listener_function)
{
ancestor_element.addEventListener(event_type, function(event)
{
if (event.target && event.target.matches && event.target.matches(target_element_selector))
{
(listener_function)(event);
}
});
}
클릭 이벤트에 사용하는 방법은 다음과 같습니다.
delegate_event('click', document, '.alert-button', your_function_here);
이와 유사한 작업을 수행할 수 있습니다.
// 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);
이를 돕기 위해 작은 라이브러리를 만들었습니다. 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() 메서드를 사용하여 지정된 선택기에 대해 대상 요소를 테스트합니다.이벤트가 트리거되면 대상 요소가 주어진 선택기와 일치할 경우에만 콜백이 호출됩니다.
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 이상
jillykate works에서 게시한 솔루션을 찾았지만 대상 요소가 가장 많이 중첩된 경우에만 해당됩니다.만약 그렇지 않다면, 이는 부모에 대해 반복함으로써 해결될 수 있습니다.
function on_window_click(event)
{
let e = event.target;
while (e !== null)
{
// --- Handle clicks here, e.g. ---
if (e.getAttribute(`data-say_hello`))
{
console.log("Hello, world!");
}
e = e.parentElement;
}
}
window.addEventListener("click", on_window_click);
또한 속성에 따라 이벤트를 처리하거나 청취자를 연결할 수 있습니다.위의 코드는 사용자 지정 속성을 사용하며,window
. 다양한 방법들 사이에 실용적인 차이가 있을지 의문입니다.
주제가 너무 오래된 것은 알지만, 순수한 것을 사용하여 잘 작동하고 매우 쉽게 작동하는 매우 유용한 코드를 만들기 위해 몇 분의 시간을 할애했습니다.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>
이것을 위한 간단한 기능을 만들었습니다.
그_case
function을 사용하면 대상을 얻을 수 있을 뿐만 아니라 이벤트를 바인딩하는 상위 요소를 얻을 수 있습니다.
콜백 함수는 대상을 고정하는 이벤트를 반환합니다 (evt.target
) 및 셀렉터와 일치하는 부모 요소(this
요소를 클릭한 후 필요한 작업을 수행할 수 있습니다.
아직 어느 쪽이 더 나은지 결정하지 못했습니다.if-else
아니면switch
var _case = function(evt, selector, cb) {
var _this = evt.target.closest(selector);
if (_this && _this.nodeType) {
cb.call(_this, evt);
return true;
} else { return false; }
}
document.getElementById('ifelse').addEventListener('click', function(evt) {
if (_case(evt, '.parent1', function(evt) {
console.log('1: ', this, evt.target);
})) return false;
if (_case(evt, '.parent2', function(evt) {
console.log('2: ', 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: ', this, evt.target);
}): break;
case _case(evt, '.parent4', function(evt) {
console.log('4: ', 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>
도움이 되길 바랍니다!
First of all add the dynamic class to the dynamically created inputboxes
var ele = document.createElement('textarea');
ele.className = "css-class-name"; // set the CSS class
ele.setAttribute('type', 'textarea');
ele.setAttribute('value', '');
ele.setAttribute("id", `row${rcount}_${c}`);
then do the following
const btns = document.querySelectorAll('.css-class-name');
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('keyup', function (e) {
console.log(e.target.id);
let textValues = $(`#${e.target.id}`).val()
console.log("=============values =====", textValues)
//on key press take id and set value of that id what i am inputting.
});
}
@Pikamander2 솔루션은 문서나 본문에 대한 이벤트 바인딩을 포함하지 않기 때문에 마음에 듭니다(문서를 클릭할 때마다 수십 개의 이벤트 핸들러가 트리거되어 언젠가는 깨어날 것입니다...).
Pikamander2 솔루션의 개선 사항입니다.
동적으로 추가된 자식 자체가 자식이 있는 돔 요소인 경우(ex:<button><u>label</u></button>
,그e.target
반환할 수도 있습니다.<u>
요소.따라서 다음을 사용할 수 있습니다.
function delegateEvent( eventType, ancestorElem, childSelector, eventHandler ) {
// Cancel if ancestorElem does not exists
if( ! ancestorElem || ( typeof ancestorElem === 'string' && ! ( ancestorElem = document.querySelector( ancestorElem ) ) ) ) {
return
}
ancestorElem.addEventListener( eventType, e => {
if( e.target && e.target.closest && e.target.closest( childSelector ) ) {
( eventHandler )( e )
}
} )
}
함수가 요소가 아닌 상위 항목에 대한 선택기를 받아들이도록 하기 위해 스니펫도 추가했습니다.
이것은 오래된 질문입니다. 하지만 저는 이 문제로 많은 시간을 보냈습니다.내 해결책이 누군가에게 도움이 될 수도 있습니다.
컨텍스트:Ajax 응답에서 동적으로 생성된 요소에 이벤트 수신기를 첨부합니다.클릭 또는 키보드 탐색을 통해 선택 가능:두 경우 모두 동일한 함수를 호출합니다.
첫번째 줄은 작동했고, 두번째 줄은 항목을 클릭할 수 없었습니다.
item.addEventListener("mouseover", this.mouseOver.bind(this) )
item.addEventListener("click", this.clickedItem.bind(this) )
그러나 이는 계속해서 효과가 있었습니다.
item.click();
(클릭 이벤트가 추가되었음을 알려주고, 해당 기능을 호출하였으나 마우스가 클릭 이벤트를 발송하지 않음)
해결책은 다음과 같습니다.
item.addEventListener("click", this.clickedItem.bind(this) )
다음 항목에 대해:
item.addEventListener("mousedown", this.clickedItem.bind(this) )
예전 SO 메시지에서 다음과 같이 제안한 것을 보았습니다.<div>s
마우스 클릭 이벤트에 응답하지 않습니다. 그러나 내가 읽은 모든 문서는 이와 모순됩니다.
그래서, 여기서 무슨 일이 일어나고 있는지 모르겠어요.
언급URL : https://stackoverflow.com/questions/34896106/attach-event-to-dynamic-elements-in-javascript
'sourcecode' 카테고리의 다른 글
'SELECT'를 사용하여 함수 호출 (0) | 2023.10.25 |
---|---|
Android 앱을 프로그래밍적으로 "다시 시작"하려면 어떻게 해야 합니까? (0) | 2023.10.25 |
바인딩 값이 변경될 때 AngularJS 트리거 ng-animate (0) | 2023.10.25 |
PowerShell 스크립트에서 C# .cs 파일 실행 (0) | 2023.10.25 |
$templateRequestProvider의 Angularjs 알 수 없는 공급자 (0) | 2023.10.25 |