Search code examples
javascripthtmlmethodsthis

Adding a class function to a dynamically generated button JS/HTML


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


Solution

  • 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>