简体   繁体   中英

How to handle events in dynamically created elements in js

I want to add the click event to a created Element dynamically that when user click on button create some elements (elements that show in code below) and when user click on element named remov must run function named deltion BUT that doesnt work .How can I implemented that?

I use Vue js

methods: {
        showinfo: function() {
            db.collection("Studnets")
                .get()
                .then(function(querySnapshot) {
                    querySnapshot.forEach(function(doc) {
const student = document.createElement("tr");
const email = document.createElement("td");
email.innerText = doc.data().email;

const name = document.createElement("td");
name.innerText = doc.data().name;

const phone = document.createElement("td");
phone.innerText = doc.data().phone;

const stage = document.createElement("td");
stage.innerText = doc.data().stage;

const remov = document.createElement("button");
const pic = document.createElement("img");
pic.setAttribute("src","/dist/delete.svg?afdf9975229cdc15458e851b478bb6cb");
remov.classList.add("del");

//the problem
remov.addEventListener("click", this.deltion());

student.appendChild(email);
student.appendChild(name);
student.appendChild(phone);
student.appendChild(stage);
student.appendChild(remov);
remov.appendChild(pic);
document.getElementById("studentList").appendChild(student);
},

  deltion: function(e) {
         const rawStudent = e.target;
         const raw = rawStudent.parentElement;
         console.log(raw);
         raw.remove();
     }

There are three issues with your code.

First Issue: invoking a function on the event listener

you are calling the deltion (maybe you mean deletion:P) function when you register the event listener.

remov.addEventListener("click", this.deltion());

the correct form is

remov.addEventListener("click", this.deltion);

Because you want to pass the function body to the event listener, not the function result. (you can wrap the function in an arrow function if you want to call it, but at the end is the same).

Second Issue: this is not this

If you fix the first one, you'll find another one (the life of programmers). this is a special keyword in js, the context of this will change depending on the caller.

  1. showinfo is called the this keyword refers to the component instance.
  2. db.collection("Studnets").get().then(function(querySnapshot) {}) promise is called and on resolve it will call the function that has querySnapshot parameter. **this** keyword context changes.
  3. you iterate the collection with a foreach querySnapshot.forEach(function(doc) {}) **this** keyword context is changed again.

A solution will be to use arrow functions so this don't get bonded to the parent function.

db.collection("Studnets").get().then(querySnapshot => {
    querySnapshot.data.forEach(doc => { 
        // code
    })
}) 

If for some reason you can't use arrow functions, you can add a variable that "shadows" the context of the this keyword on the showinfo function.

showinfo() {
    const vm = this;
    api.getStudentsCollection().then(function(querySnapshot) {
      querySnapshot.data.forEach(function(doc) {
        // setup code
        remov.addEventListener("click", vm.deltion);
        // setup code
      });
    });
}

Third Issue: clicking the arrow image will delete the button but not the tr Use currentTarget instead of the target, the target is the element the user click, it can be any element inside the button like the image, currentTarget is the element that the event listener is attached aka the button.

{
    deltion: function(e) {
        const rawStudent = e.currentTarget;
        const raw = rawStudent.parentElement;
        console.log(raw);
        raw.remove();
    }
}

Unsolicited Advice

Vue excels with its simplicity and declarative code. You can solve the problem like your original code, but there is a simpler way to let the component manage its state .

I replicated your code with the original version fixed and the simplest vue way (with a simple empty and loading state toggle). Hope you find it useful and learn from this. :) https://codesandbox.io/s/student-list-ammar-yasir-b5sxo?file=/src/App.vue

Learning references

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM