Cruxer
Cruxer

Reputation: 21

Select2 triggering change event

I, not so long ago, went ahead and built an html dependent dropdown which pulls it's data from an array in the js. The dependencies worked perfectly fine until I realized that I needed to add a search function to the dropdown.

I went through different alternatives and to me the simplest option was to use select2 plugin. The problem I am having is that when using select2, it doesn't seem to be triggering the EventListener (Line 43 in JS) I had previously setup for the regular select.

Find below what I have attempted:

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/select2.min.css" rel="stylesheet" />
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/select2.min.js"></script>

    <title>Document</title>


</head>
<body>
    <select id ="level1"  style='width: 300px;'></select>
    <select id ="level2"  style='width: 300px;'></select>
    <select id ="level3"  style='width: 300px;'></select>
    <hr>
    
    <select id ="level4" disabled></select>
    <select id ="level5" disabled></select>
    <select id ="level6" disabled></select>
    <select id ="level7" disabled></select>
    <hr>
    <h1 id ="level8"></h1>

    <script src="betterdd.js"></script>

</body>
</html>

JS: (Select options are found in var myData = [...])

class DropDown {

    constructor(data){
        this.data = data;
        this.targets = [];
    }

    filterData(filtersAsArray){
        return this.data.filter(r => filtersAsArray.every((item,i) => item === r[i]));
    }

    getUniqueValues(dataAsArray,index){
        const uniqueOptions = new Set();
        dataAsArray.forEach(r => uniqueOptions.add(r[index]));
        return [...uniqueOptions];
    }

    populateDropDown(el,listAsArray){
        el.innerHTML = "";
    
        listAsArray.forEach(item => {
            const option = document.createElement("option");
            option.textContent = item;
            el.appendChild(option);
        });
    }

    createPopulateDropDownFunction(el,elsDependsOn){
        return () => {
        const elsDependsOnValues = elsDependsOn.length === 0 ? null : elsDependsOn.map(depEl => depEl.value);
        const dataToUse = elsDependsOn.length === 0 ? this.data : this.filterData (elsDependsOnValues);
        const listToUse = this.getUniqueValues(dataToUse, elsDependsOn.length); 
        this.populateDropDown(el,listToUse);
        }
    }

    add(options){
        //{target: "level2", dependsOn: ["level1"] }
        const el = document.getElementById(options.target);
        const elsDependsOn = options.dependsOn.length === 0 ? [] : options.dependsOn.map(id => document.getElementById(id));
        const eventFunction = this.createPopulateDropDownFunction (el, elsDependsOn);
        const targetObject = { el: el, elsDependsOn: elsDependsOn,func: eventFunction};
        targetObject.elsDependsOn.forEach(depEl => depEl.addEventListener("change",eventFunction));
        this.targets.push(targetObject);
        return this;
    }

    initialize(){
        this.targets.forEach(t => t.func());
        return this;
    }

    eazyDropDown(arrayOfIds){
        arrayOfIds.forEach((item,i) =>{
            const option = {target: item, dependsOn: arrayOfIds.slice(0,i) }
            this.add(option);
        });
        this.initialize();
        return this;
    }

}
var dd = new DropDown(myData).eazyDropDown(["level1","level2","level3","level4","level5","level6","level7","level8"])

Upvotes: 0

Views: 408

Answers (1)

Raul.F
Raul.F

Reputation: 11

add the following line inside add method :

const eventFunction = this.createPopulateDropDownFunction (el, elsDependsOn);
el.addEventListener("change", (e) => {
    eventFunction();
    console.log(e.target.value)
})

and remove the following line:

targetObject.elsDependsOn.forEach(depEl => depEl.addEventListener("change",eventFunction));

Upvotes: 1

Related Questions