Home > Blockchain >  Adding a class function to a dynamically generated button JS/HTML
Adding a class function to a dynamically generated button JS/HTML

Time:11-28

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>

  • Related