I'm currently working on an application which needs to automatically generate an HTML page which is based on the data provided by the server side. I have made the current code:
//Indicator class
class Button_class{
constructor(name)
{
this.buttonAva = false;
this.name = name;
this.buttonIdHTML = '"' name "But" '"'
}
button_action()
{
//This is an abstract method
console.log("foo")
}
//This method creates the button
create_Button()
{
//Make sure that the method is only executed once
if (this.buttonAva == false)
{
//Get the element id
root22 = document.getElementById('root');
//create the HTML code
let html ="<button id=" this.indicatorIdHTML "type='button' onclick = 'button_action()/> Click Me!";
root22.insertAdjacentHTML("beforeend", html);
html = "<p>"
root22.insertAdjacentHTML("beforeend", html);
}
}
}
//----------------------------------------------------------
//function for setting up the page
function process_init(){
for (let i = 0; i < data.Indicators.length; i ){
//Create the HTML for the indicators
let temp_indi = new Indicator(data.Indicators[i]);
indicators.push(temp_indi);
indicators.push(data.Indicators[i])
//Build the HTML page
indicators[i].create_Indicator()
indicators[i].create_Button()
}
}
The error i'm getting is the following: button_action is not defined I tried to call the function under THIS^.button_action() but no results here. Is a setup like this even possible in JS, and if yes how could I get this to work? Thank you in advance Greetings Alex
CodePudding user response:
The method you are calling is isolated from the global scope, meaning you are not able to call this method because the function is not exposed in the global scope.
You can achieve what you're trying to do (assuming you're just using vanilla js) by using the DOM.createElement
method, and binding this function on the element directly using elm.onclick
.
Here's an example of how you might achieve this
let btn = document.createElement('button', { id: this.indicatorIdHTML });
root22.insertAdjacentElement('beforeend', btn);
CodePudding user response:
There is an error with the ID you assign - it is not within quotes (ok) but runs into the type
attribute.
The button
tag itself needs a closing </button>
unlike an input of type button
which would not.
You cannot add the button_method
inline within the string as you do above so instead query the DOM once the button has been appended and assign the event listener.
class Button_class{
constructor(name)
{
this.buttonAva = false;
this.name = name;
this.buttonIdHTML = '"' name "But" '"'
}
button_action()
{
//This is an abstract method
console.log("foo")
}
//This method creates the button
create_Button()
{
//Make sure that the method is only executed once
if (this.buttonAva == false)
{
//Get the element id
let root22 = document.getElementById('root');
//create the HTML code
let html =`<button id='${this.indicatorIdHTML}' type='button'>Click Me!</button>`;
root22.insertAdjacentHTML("beforeend", html);
html = "<p>"
root22.insertAdjacentHTML("beforeend", html);
root22.querySelector(`button[id="${this.indicatorIdHTML}"]`).addEventListener('click',this.button_action);
}
}
}
let bttn=new Button_class('geronimo')
bttn.create_Button()
#root{
border:1px solid red;
padding:1rem;
}
#root button{
border:1px solid blue;
}
<div id='root'></div>
CodePudding user response:
You can bind the click event to your button like below.
The arrow function should allow you to access this
in the button_action
too. Example to call this.name
//Indicator class
class Button_class{
constructor(name)
{
this.buttonAva = false;
this.name = name;
this.buttonIdHTML = '"' name "But" '"'
}
button_action()
{
//This is an abstract method
console.log("foo. my name is: " this.name)
}
//This method creates the button
create_Button()
{
//Make sure that the method is only executed once
if (this.buttonAva == false)
{
//Get the element id
const root22 = document.getElementById('root');
// bind a click event to the button
// and trigger the button_action
let html =`<button id="${this.indicatorIdHTML}" type='button'>Click Me!</button>`;
root22.innerHTML = html
document.getElementById(this.indicatorIdHTML).addEventListener('click', ()=>this.button_action())
}
}
}
const b1 = new Button_class('My First Button!')
b1.create_Button()
<div id="root">
</div>
or with more flexibility and future proofing, you can make reference to the HTML button element instance instead of using id, class, or any query selector. This eliminates issues when you have repeated button names resulting in duplicated id. The example below also shows how to access the button element using this.elm
which could be useful for other uses.
//Indicator class
class Button_class{
constructor(name)
{
this.buttonAva = false;
this.name = name;
this.buttonIdHTML = '"' name "But" '"'
this.elm = null
}
button_action()
{
//This is an abstract method
console.log("foo. my name is: " this.name)
}
//This method creates the button
create_Button()
{
//Make sure that the method is only executed once
if (this.buttonAva == false)
{
//Get the element id
const root22 = document.getElementById('root');
// create a button element and make a reference
// you can access this.elm for other purposes
this.elm = document.createElement("BUTTON");
this.elm.setAttribute('type', 'button')
this.elm.innerHTML = 'Click Me 2!'
this.elm.addEventListener('click', ()=>this.button_action())
root22.appendChild(this.elm)
}
}
}
const b1 = new Button_class('My Second Button!')
b1.create_Button()
console.log(b1.elm)
<div id="root">
</div>