I'm having a hard time explaining this. I'm building out a custom component, in this component there is a button. I need to be able to dynamically set the click action for that button so that its action can change depending on context. so if there are 2 instances of this component, a&b, each instance has a different function that is executed when the button inside them is clicked. I thought I could just assign a function to a property of the component and execute the property from inside the component like this:
window.customElements.define('xmp-1', class xmp1 extends HTMLElement{
constructor(){super();}
connectedCallback(){
this.innerHTML = `
<div>
<div id='test' style='width:70px; border:solid thin black;'>test button</div>
</div>`;
this.querySelector('#test').addEventListener('click', function(){
console.log('test action');
this.action1();
});
}
});
document.querySelector('xmp-1').action1 = function(){
console.log("this is the callback");
};
<xmp-1></xmp-1>
but when you run this you get an error saying the property action1
doesn't exist.
Whats the proper way to setup a callback that allows the flexibility I need?
Update: Please try the below code, where I have added a binding statement to bind "this"
<!DOCTYPE html>
<html>
<head>
<title>
</title>
</head>
<body>
<xmp-1></xmp-1>
<script>
document.querySelector('xmp-1').action1 = function(){
console.log("this is the callback");
};
window.customElements.define('xmp-1', class xmp1 extends HTMLElement {
constructor() { super();
this.handler = this.handler.bind(this);
}
handler() {
console.log("this is the test");
console.log('test action');
this.action1();
}
connectedCallback() {
this.innerHTML = `<div>
<div id='test' style='width:70px; border:solid thin black;'>test button</div>
</div>`;
this.querySelector('#test').addEventListener('click',this.handler);
}
});
</script>
</body>
</html>
Please change xmp-1 to #test in your code as shown below,
<!DOCTYPE html>
<html>
<head>
<title>
</title>
</head>
<body>
<xmp-1></xmp-1>
<script>
window.addEventListener('load', (event) => {
document.querySelector('#test').action1 = function(){
console.log("this is the callback");
};
});
window.customElements.define('xmp-1', class xmp1 extends HTMLElement {
constructor() { super(); }
connectedCallback() {
this.innerHTML = `<div>
<div id='test' style='width:70px; border:solid thin black;'>test button</div>
</div>`;
this.querySelector('#test').addEventListener('click', function () {
console.log('test action');
this.action1();
});
}
});
</script>
</body>
</html>
Or please try approach2 as shown below, where you must add a function called this.querySelector('#test').action1 to your custom element.
<!DOCTYPE html>
<html>
<head>
<title>
</title>
</head>
<body>
<xmp-1></xmp-1>
<script>
window.customElements.define('xmp-1', class xmp1 extends HTMLElement {
constructor() { super(); }
connectedCallback() {
this.innerHTML = `<div>
<div id='test' style='width:70px; border:solid thin black;'>test button</div>
</div>`;
this.querySelector('#test').addEventListener('click', function () {
console.log('test action');
this.action1();
});
this.querySelector('#test').action1 = function() {
console.log('test action1');
}
}
});
</script>
</body>
</html>