Home > Back-end >  Multiple event listeners being added to dynamically created elements
Multiple event listeners being added to dynamically created elements

Time:11-25

I am creating and appending elements via class object constructor with a button press, and need each individual element created to have an event listener that will call a method from a class to return the values of the object tied to the element.

Everything seems to work fine when I have a single element that was created. When I have two or more elements, it will output n results where n = the amount of elements that were created. 4 elements created = 4x the outputs, which ruins anything that I want to do with the data output.

For example, if I have one element that has the properties of square and red, then clicking it correctly outputs square and red. But if I add an element with the object properties of circle and green, then clicking on EITHER element will output both 'square red' and 'circle green'

// Utility function
function onEvent(event, selector, callback) {
    return selector.addEventListener(event, callback);
}

onEvent('click', submit, function() {
    let shape = new Shape(shapeInput.value, colorInput.value);
    shape.createShape();
    output.innerHTML = `${shape.shapeColor} ${shape.shapeName} `

    shapeContainer.addEventListener('click', function (e) {
        let target = e.target;

        if (target.matches('div')) {
            output.innerHTML = `${shape.getInfo()}`;
        }
    });
});

I have tried looking for ways to check if the element already has an event listener and to ignore it, but didn't have any luck. I have also tried to add a removeEventListener section, to no success. Is there something I'm missing here or am I completely wrong with my approach?

CodePudding user response:

Hope I did not respond let. this will work for you.

   'use strict';

    // Selectors 
    const shapeContainer = select('.shape-container');
    const submit = select('.submit');
    const shapeInput = select('.shape-input');
    const colorInput = select('.color-input');
    const shapeSelector = select('.shape');
    const output = select('span');


    class Shape {
        constructor(name, color) {
            this._name = name;
            this._color = color;
        }

        set shapeName(name) {
            if (name instanceof Shape && this._name.length > 0) {
                this._name = name;
            } else {
                throw new TypeError('Shape name is invalid');
            }
        }

        get shapeName() {
            return this._name;
        }

        set shapeColor(color) {
            if (color instanceof Shape && this._color.length > 0) {
                this._color = color;
            } else {
                throw new TypeError('Color is invalid');
            }
        }

        get shapeColor() {
            return this._color;
        }

        createShape() {

            let element = {
                tag : document.createElement('div'),
                color : this._color,
                name : this._name,
            }

            document.querySelector('.shape-container').appendChild(element.tag);
            element.tag.style.cssText  = 'background-color:'   element.color;

            // Shape definition
            if (this._name == 'circle') {
                element.tag.classList.add('circle', 'shape');
            } else if (this._name == 'square') {
                element.tag.classList.add('square', 'shape');
            } else {
                throw new TypeError('shapeName is invalid');
            }
            element.tag.addEventListener('click', function () {
                console.log(element.color," ",element.name)
                if (element.tag.matches('div')) {
                    output.innerHTML = getInfo(element);
                }
            });
        }
    }
    // Utility functions 
    
    function select(selector, parent = document) {
        return parent.querySelector(selector);
    }

     function onEvent(event, selector, callback) {
        return selector.addEventListener(event, callback);
    }

    function getInfo (e) {
        console.log(e.color,e.name)
        return `${e.name} ${e.color}`;
    }

    let arr = [];

    onEvent('click', submit, function () {
        let shape = new Shape(shapeInput.value, colorInput.value);
        arr.push(shape);
        console.log(arr);
        shape.createShape();
    });
  • Related